diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-18 15:57:52 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-18 15:57:52 -0400 |
commit | 5bae7ac9feba925fd0099057f6b23d7be80b7b41 (patch) | |
tree | 7ff78cda1d18a7b5eb5c6384815bb8f7b87cf5ce | |
parent | 97405fe26b2a4df7090884b086ee8224ace2a6d1 (diff) | |
parent | 587ca7619a150cef0ce0dd8fd08c367e502f0421 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hskinnemoen/avr32-2.6:
[AVR32] Initialize phy_mask for both macb devices
[AVR32] Fix atomic_add_unless() and atomic_sub_unless()
[AVR32] Correct misspelled CONFIG_BLK_DEV_INITRD variable.
[AVR32] Fix build error in parse_tag_rdimg()
[AVR32] Don't wire up macb0 unless SW6 is in default position
[AVR32] Wire up SSC platform device 0 as TX on ATSTK1000 board
[AVR32] Add Atmel SSC driver platform device to AT32AP architecture
[AVR32] Remove optimization of unaligned word loads
[AVR32] Make STK1000 mux settings configurable
[AVR32] CPU frequency scaling for AT32AP
[AVR32] Split SM device into PM, RTC, WDT and EIC
[AVR32] faster avr32 unaligned access
-rw-r--r-- | arch/avr32/Kconfig | 25 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/Kconfig | 53 | ||||
-rw-r--r-- | arch/avr32/boards/atstk1000/atstk1002.c | 50 | ||||
-rw-r--r-- | arch/avr32/kernel/setup.c | 4 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/Makefile | 1 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap.c | 31 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap7000.c | 340 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/cpufreq.c | 112 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/extint.c | 200 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/pm.h | 112 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/sm.h | 242 | ||||
-rw-r--r-- | include/asm-avr32/arch-at32ap/board.h | 14 | ||||
-rw-r--r-- | include/asm-avr32/arch-at32ap/sm.h | 27 | ||||
-rw-r--r-- | include/asm-avr32/atomic.h | 4 | ||||
-rw-r--r-- | include/asm-avr32/unaligned.h | 15 |
15 files changed, 751 insertions, 479 deletions
diff --git a/arch/avr32/Kconfig b/arch/avr32/Kconfig index 3ec76586877e..d12346aaa88b 100644 --- a/arch/avr32/Kconfig +++ b/arch/avr32/Kconfig | |||
@@ -113,6 +113,10 @@ config BOARD_ATNGW100 | |||
113 | bool "ATNGW100 Network Gateway" | 113 | bool "ATNGW100 Network Gateway" |
114 | endchoice | 114 | endchoice |
115 | 115 | ||
116 | if BOARD_ATSTK1000 | ||
117 | source "arch/avr32/boards/atstk1000/Kconfig" | ||
118 | endif | ||
119 | |||
116 | choice | 120 | choice |
117 | prompt "Boot loader type" | 121 | prompt "Boot loader type" |
118 | default LOADER_U_BOOT | 122 | default LOADER_U_BOOT |
@@ -185,6 +189,27 @@ config CMDLINE | |||
185 | 189 | ||
186 | endmenu | 190 | endmenu |
187 | 191 | ||
192 | menu "Power managment options" | ||
193 | |||
194 | menu "CPU Frequency scaling" | ||
195 | |||
196 | source "drivers/cpufreq/Kconfig" | ||
197 | |||
198 | config CPU_FREQ_AT32AP | ||
199 | bool "CPU frequency driver for AT32AP" | ||
200 | depends on CPU_FREQ && PLATFORM_AT32AP | ||
201 | default n | ||
202 | help | ||
203 | This enables the CPU frequency driver for AT32AP processors. | ||
204 | |||
205 | For details, take a look in <file:Documentation/cpu-freq>. | ||
206 | |||
207 | If in doubt, say N. | ||
208 | |||
209 | endmenu | ||
210 | |||
211 | endmenu | ||
212 | |||
188 | menu "Bus options" | 213 | menu "Bus options" |
189 | 214 | ||
190 | config PCI | 215 | config PCI |
diff --git a/arch/avr32/boards/atstk1000/Kconfig b/arch/avr32/boards/atstk1000/Kconfig new file mode 100644 index 000000000000..71bc7d364fb7 --- /dev/null +++ b/arch/avr32/boards/atstk1000/Kconfig | |||
@@ -0,0 +1,53 @@ | |||
1 | # STK1000 customization | ||
2 | |||
3 | if BOARD_ATSTK1002 | ||
4 | |||
5 | config BOARD_ATSTK1002_CUSTOM | ||
6 | bool "Non-default STK-1002 jumper settings" | ||
7 | help | ||
8 | You will normally leave the jumpers on the CPU card at their | ||
9 | default settings. If you need to use certain peripherals, | ||
10 | you will need to change some of those jumpers. | ||
11 | |||
12 | if BOARD_ATSTK1002_CUSTOM | ||
13 | |||
14 | config BOARD_ATSTK1002_SW1_CUSTOM | ||
15 | bool "SW1: use SSC1 (not SPI0)" | ||
16 | help | ||
17 | This also prevents using the external DAC as an audio interface, | ||
18 | and means you can't initialize the on-board QVGA display. | ||
19 | |||
20 | config BOARD_ATSTK1002_SW2_CUSTOM | ||
21 | bool "SW2: use IRDA or TIMER0 (not UART-A, MMC/SD, and PS2-A)" | ||
22 | help | ||
23 | If you change this you'll want an updated boot loader putting | ||
24 | the console on UART-C not UART-A. | ||
25 | |||
26 | config BOARD_ATSTK1002_SW3_CUSTOM | ||
27 | bool "SW3: use TIMER1 (not SSC0 and GCLK)" | ||
28 | help | ||
29 | This also prevents using the external DAC as an audio interface. | ||
30 | |||
31 | config BOARD_ATSTK1002_SW4_CUSTOM | ||
32 | bool "SW4: use ISI/Camera (not GPIOs, SPI1, and PS2-B)" | ||
33 | help | ||
34 | To use the camera interface you'll need a custom card (on the | ||
35 | PCI-format connector) connect a video sensor. | ||
36 | |||
37 | config BOARD_ATSTK1002_SW5_CUSTOM | ||
38 | bool "SW5: use MACB1 (not LCDC)" | ||
39 | |||
40 | config BOARD_ATSTK1002_SW6_CUSTOM | ||
41 | bool "SW6: more GPIOs (not MACB0)" | ||
42 | |||
43 | endif # custom | ||
44 | |||
45 | config BOARD_ATSTK1002_SPI1 | ||
46 | bool "Configure SPI1 controller" | ||
47 | depends on !BOARD_ATSTK1002_SW4_CUSTOM | ||
48 | help | ||
49 | All the signals for the second SPI controller are available on | ||
50 | GPIO lines and accessed through the J1 jumper block. Say "y" | ||
51 | here to configure that SPI controller. | ||
52 | |||
53 | endif # stk 1002 | ||
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index e253e86a1a39..cb93eabb9c6c 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c | |||
@@ -27,15 +27,27 @@ | |||
27 | 27 | ||
28 | #include "atstk1000.h" | 28 | #include "atstk1000.h" |
29 | 29 | ||
30 | #define SW2_DEFAULT /* MMCI and UART_A available */ | ||
31 | 30 | ||
32 | struct eth_addr { | 31 | struct eth_addr { |
33 | u8 addr[6]; | 32 | u8 addr[6]; |
34 | }; | 33 | }; |
35 | 34 | ||
36 | static struct eth_addr __initdata hw_addr[2]; | 35 | static struct eth_addr __initdata hw_addr[2]; |
37 | static struct eth_platform_data __initdata eth_data[2]; | 36 | static struct eth_platform_data __initdata eth_data[2] = { |
37 | { | ||
38 | /* | ||
39 | * The MDIO pullups on STK1000 are a bit too weak for | ||
40 | * the autodetection to work properly, so we have to | ||
41 | * mask out everything but the correct address. | ||
42 | */ | ||
43 | .phy_mask = ~(1U << 16), | ||
44 | }, | ||
45 | { | ||
46 | .phy_mask = ~(1U << 17), | ||
47 | }, | ||
48 | }; | ||
38 | 49 | ||
50 | #ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM | ||
39 | static struct spi_board_info spi0_board_info[] __initdata = { | 51 | static struct spi_board_info spi0_board_info[] __initdata = { |
40 | { | 52 | { |
41 | /* QVGA display */ | 53 | /* QVGA display */ |
@@ -45,6 +57,13 @@ static struct spi_board_info spi0_board_info[] __initdata = { | |||
45 | .mode = SPI_MODE_3, | 57 | .mode = SPI_MODE_3, |
46 | }, | 58 | }, |
47 | }; | 59 | }; |
60 | #endif | ||
61 | |||
62 | #ifdef CONFIG_BOARD_ATSTK1002_SPI1 | ||
63 | static struct spi_board_info spi1_board_info[] __initdata = { { | ||
64 | /* patch in custom entries here */ | ||
65 | } }; | ||
66 | #endif | ||
48 | 67 | ||
49 | /* | 68 | /* |
50 | * The next two functions should go away as the boot loader is | 69 | * The next two functions should go away as the boot loader is |
@@ -103,10 +122,10 @@ static void __init set_hw_addr(struct platform_device *pdev) | |||
103 | 122 | ||
104 | void __init setup_board(void) | 123 | void __init setup_board(void) |
105 | { | 124 | { |
106 | #ifdef SW2_DEFAULT | 125 | #ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM |
107 | at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */ | ||
108 | #else | ||
109 | at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */ | 126 | at32_map_usart(0, 1); /* USART 0/B: /dev/ttyS1, IRDA */ |
127 | #else | ||
128 | at32_map_usart(1, 0); /* USART 1/A: /dev/ttyS0, DB9 */ | ||
110 | #endif | 129 | #endif |
111 | /* USART 2/unused: expansion connector */ | 130 | /* USART 2/unused: expansion connector */ |
112 | at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */ | 131 | at32_map_usart(3, 2); /* USART 3/C: /dev/ttyS2, DB9 */ |
@@ -140,18 +159,31 @@ static int __init atstk1002_init(void) | |||
140 | 159 | ||
141 | at32_add_system_devices(); | 160 | at32_add_system_devices(); |
142 | 161 | ||
143 | #ifdef SW2_DEFAULT | 162 | #ifdef CONFIG_BOARD_ATSTK1002_SW2_CUSTOM |
144 | at32_add_device_usart(0); | ||
145 | #else | ||
146 | at32_add_device_usart(1); | 163 | at32_add_device_usart(1); |
164 | #else | ||
165 | at32_add_device_usart(0); | ||
147 | #endif | 166 | #endif |
148 | at32_add_device_usart(2); | 167 | at32_add_device_usart(2); |
149 | 168 | ||
169 | #ifndef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM | ||
150 | set_hw_addr(at32_add_device_eth(0, ð_data[0])); | 170 | set_hw_addr(at32_add_device_eth(0, ð_data[0])); |
151 | 171 | #endif | |
172 | #ifndef CONFIG_BOARD_ATSTK1002_SW1_CUSTOM | ||
152 | at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); | 173 | at32_add_device_spi(0, spi0_board_info, ARRAY_SIZE(spi0_board_info)); |
174 | #endif | ||
175 | #ifdef CONFIG_BOARD_ATSTK1002_SPI1 | ||
176 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); | ||
177 | #endif | ||
178 | #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM | ||
179 | set_hw_addr(at32_add_device_eth(1, ð_data[1])); | ||
180 | #else | ||
153 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, | 181 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, |
154 | fbmem_start, fbmem_size); | 182 | fbmem_start, fbmem_size); |
183 | #endif | ||
184 | #ifndef CONFIG_BOARD_ATSTK1002_SW3_CUSTOM | ||
185 | at32_add_device_ssc(0, ATMEL_SSC_TX); | ||
186 | #endif | ||
155 | 187 | ||
156 | return 0; | 188 | return 0; |
157 | } | 189 | } |
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index b279d66acf5f..d08b0bc6b2bb 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c | |||
@@ -313,7 +313,7 @@ __tagtable(ATAG_MEM, parse_tag_mem); | |||
313 | 313 | ||
314 | static int __init parse_tag_rdimg(struct tag *tag) | 314 | static int __init parse_tag_rdimg(struct tag *tag) |
315 | { | 315 | { |
316 | #ifdef CONFIG_INITRD | 316 | #ifdef CONFIG_BLK_DEV_INITRD |
317 | struct tag_mem_range *mem = &tag->u.mem_range; | 317 | struct tag_mem_range *mem = &tag->u.mem_range; |
318 | int ret; | 318 | int ret; |
319 | 319 | ||
@@ -323,7 +323,7 @@ static int __init parse_tag_rdimg(struct tag *tag) | |||
323 | return 0; | 323 | return 0; |
324 | } | 324 | } |
325 | 325 | ||
326 | ret = add_reserved_region(mem->start, mem->start + mem->size - 1, | 326 | ret = add_reserved_region(mem->addr, mem->addr + mem->size - 1, |
327 | "initrd"); | 327 | "initrd"); |
328 | if (ret) { | 328 | if (ret) { |
329 | printk(KERN_WARNING | 329 | printk(KERN_WARNING |
diff --git a/arch/avr32/mach-at32ap/Makefile b/arch/avr32/mach-at32ap/Makefile index f1d395724ac6..a8b445046e3e 100644 --- a/arch/avr32/mach-at32ap/Makefile +++ b/arch/avr32/mach-at32ap/Makefile | |||
@@ -1,3 +1,4 @@ | |||
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 | 3 | obj-$(CONFIG_CPU_AT32AP7000) += time-tc.o |
4 | obj-$(CONFIG_CPU_FREQ_AT32AP) += cpufreq.o | ||
diff --git a/arch/avr32/mach-at32ap/at32ap.c b/arch/avr32/mach-at32ap/at32ap.c index 90f207e8e96d..7c4987f3287a 100644 --- a/arch/avr32/mach-at32ap/at32ap.c +++ b/arch/avr32/mach-at32ap/at32ap.c | |||
@@ -11,41 +11,10 @@ | |||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | 13 | ||
14 | #include <asm/io.h> | ||
15 | |||
16 | #include <asm/arch/init.h> | 14 | #include <asm/arch/init.h> |
17 | #include <asm/arch/sm.h> | ||
18 | |||
19 | struct at32_sm system_manager; | ||
20 | |||
21 | static int __init at32_sm_init(void) | ||
22 | { | ||
23 | struct resource *regs; | ||
24 | struct at32_sm *sm = &system_manager; | ||
25 | int ret = -ENXIO; | ||
26 | |||
27 | regs = platform_get_resource(&at32_sm_device, IORESOURCE_MEM, 0); | ||
28 | if (!regs) | ||
29 | goto fail; | ||
30 | |||
31 | spin_lock_init(&sm->lock); | ||
32 | sm->pdev = &at32_sm_device; | ||
33 | |||
34 | ret = -ENOMEM; | ||
35 | sm->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
36 | if (!sm->regs) | ||
37 | goto fail; | ||
38 | |||
39 | return 0; | ||
40 | |||
41 | fail: | ||
42 | printk(KERN_ERR "Failed to initialize System Manager: %d\n", ret); | ||
43 | return ret; | ||
44 | } | ||
45 | 15 | ||
46 | void __init setup_platform(void) | 16 | void __init setup_platform(void) |
47 | { | 17 | { |
48 | at32_sm_init(); | ||
49 | at32_clock_init(); | 18 | at32_clock_init(); |
50 | at32_portmux_init(); | 19 | at32_portmux_init(); |
51 | } | 20 | } |
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 | } |
diff --git a/arch/avr32/mach-at32ap/cpufreq.c b/arch/avr32/mach-at32ap/cpufreq.c new file mode 100644 index 000000000000..235524b79193 --- /dev/null +++ b/arch/avr32/mach-at32ap/cpufreq.c | |||
@@ -0,0 +1,112 @@ | |||
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 | /*#define DEBUG*/ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/cpufreq.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <asm/system.h> | ||
22 | |||
23 | static struct clk *cpuclk; | ||
24 | |||
25 | static int at32_verify_speed(struct cpufreq_policy *policy) | ||
26 | { | ||
27 | if (policy->cpu != 0) | ||
28 | return -EINVAL; | ||
29 | |||
30 | cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, | ||
31 | policy->cpuinfo.max_freq); | ||
32 | return 0; | ||
33 | } | ||
34 | |||
35 | static unsigned int at32_get_speed(unsigned int cpu) | ||
36 | { | ||
37 | /* No SMP support */ | ||
38 | if (cpu) | ||
39 | return 0; | ||
40 | return (unsigned int)((clk_get_rate(cpuclk) + 500) / 1000); | ||
41 | } | ||
42 | |||
43 | static int at32_set_target(struct cpufreq_policy *policy, | ||
44 | unsigned int target_freq, | ||
45 | unsigned int relation) | ||
46 | { | ||
47 | struct cpufreq_freqs freqs; | ||
48 | long freq; | ||
49 | |||
50 | /* Convert target_freq from kHz to Hz */ | ||
51 | freq = clk_round_rate(cpuclk, target_freq * 1000); | ||
52 | |||
53 | /* Check if policy->min <= new_freq <= policy->max */ | ||
54 | if(freq < (policy->min * 1000) || freq > (policy->max * 1000)) | ||
55 | return -EINVAL; | ||
56 | |||
57 | pr_debug("cpufreq: requested frequency %u Hz\n", target_freq * 1000); | ||
58 | |||
59 | freqs.old = at32_get_speed(0); | ||
60 | freqs.new = (freq + 500) / 1000; | ||
61 | freqs.cpu = 0; | ||
62 | freqs.flags = 0; | ||
63 | |||
64 | cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); | ||
65 | clk_set_rate(cpuclk, freq); | ||
66 | cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); | ||
67 | |||
68 | pr_debug("cpufreq: set frequency %lu Hz\n", freq); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) | ||
74 | { | ||
75 | if (policy->cpu != 0) | ||
76 | return -EINVAL; | ||
77 | |||
78 | cpuclk = clk_get(NULL, "cpu"); | ||
79 | if (IS_ERR(cpuclk)) { | ||
80 | pr_debug("cpufreq: could not get CPU clk\n"); | ||
81 | return PTR_ERR(cpuclk); | ||
82 | } | ||
83 | |||
84 | policy->cpuinfo.min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; | ||
85 | policy->cpuinfo.max_freq = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; | ||
86 | policy->cpuinfo.transition_latency = 0; | ||
87 | policy->cur = at32_get_speed(0); | ||
88 | policy->min = policy->cpuinfo.min_freq; | ||
89 | policy->max = policy->cpuinfo.max_freq; | ||
90 | policy->governor = CPUFREQ_DEFAULT_GOVERNOR; | ||
91 | |||
92 | printk("cpufreq: AT32AP CPU frequency driver\n"); | ||
93 | |||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | static struct cpufreq_driver at32_driver = { | ||
98 | .name = "at32ap", | ||
99 | .owner = THIS_MODULE, | ||
100 | .init = at32_cpufreq_driver_init, | ||
101 | .verify = at32_verify_speed, | ||
102 | .target = at32_set_target, | ||
103 | .get = at32_get_speed, | ||
104 | .flags = CPUFREQ_STICKY, | ||
105 | }; | ||
106 | |||
107 | static int __init at32_cpufreq_init(void) | ||
108 | { | ||
109 | return cpufreq_register_driver(&at32_driver); | ||
110 | } | ||
111 | |||
112 | arch_initcall(at32_cpufreq_init); | ||
diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c index 4a60eccfebd2..8acd01090031 100644 --- a/arch/avr32/mach-at32ap/extint.c +++ b/arch/avr32/mach-at32ap/extint.c | |||
@@ -17,42 +17,83 @@ | |||
17 | 17 | ||
18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
19 | 19 | ||
20 | #include <asm/arch/sm.h> | 20 | /* EIC register offsets */ |
21 | 21 | #define EIC_IER 0x0000 | |
22 | #include "sm.h" | 22 | #define EIC_IDR 0x0004 |
23 | #define EIC_IMR 0x0008 | ||
24 | #define EIC_ISR 0x000c | ||
25 | #define EIC_ICR 0x0010 | ||
26 | #define EIC_MODE 0x0014 | ||
27 | #define EIC_EDGE 0x0018 | ||
28 | #define EIC_LEVEL 0x001c | ||
29 | #define EIC_TEST 0x0020 | ||
30 | #define EIC_NMIC 0x0024 | ||
31 | |||
32 | /* Bitfields in TEST */ | ||
33 | #define EIC_TESTEN_OFFSET 31 | ||
34 | #define EIC_TESTEN_SIZE 1 | ||
35 | |||
36 | /* Bitfields in NMIC */ | ||
37 | #define EIC_EN_OFFSET 0 | ||
38 | #define EIC_EN_SIZE 1 | ||
39 | |||
40 | /* Bit manipulation macros */ | ||
41 | #define EIC_BIT(name) \ | ||
42 | (1 << EIC_##name##_OFFSET) | ||
43 | #define EIC_BF(name,value) \ | ||
44 | (((value) & ((1 << EIC_##name##_SIZE) - 1)) \ | ||
45 | << EIC_##name##_OFFSET) | ||
46 | #define EIC_BFEXT(name,value) \ | ||
47 | (((value) >> EIC_##name##_OFFSET) \ | ||
48 | & ((1 << EIC_##name##_SIZE) - 1)) | ||
49 | #define EIC_BFINS(name,value,old) \ | ||
50 | (((old) & ~(((1 << EIC_##name##_SIZE) - 1) \ | ||
51 | << EIC_##name##_OFFSET)) \ | ||
52 | | EIC_BF(name,value)) | ||
53 | |||
54 | /* Register access macros */ | ||
55 | #define eic_readl(port,reg) \ | ||
56 | __raw_readl((port)->regs + EIC_##reg) | ||
57 | #define eic_writel(port,reg,value) \ | ||
58 | __raw_writel((value), (port)->regs + EIC_##reg) | ||
59 | |||
60 | struct eic { | ||
61 | void __iomem *regs; | ||
62 | struct irq_chip *chip; | ||
63 | unsigned int first_irq; | ||
64 | }; | ||
23 | 65 | ||
24 | static void eim_ack_irq(unsigned int irq) | 66 | static void eic_ack_irq(unsigned int irq) |
25 | { | 67 | { |
26 | struct at32_sm *sm = get_irq_chip_data(irq); | 68 | struct eic *eic = get_irq_chip_data(irq); |
27 | sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq)); | 69 | eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); |
28 | } | 70 | } |
29 | 71 | ||
30 | static void eim_mask_irq(unsigned int irq) | 72 | static void eic_mask_irq(unsigned int irq) |
31 | { | 73 | { |
32 | struct at32_sm *sm = get_irq_chip_data(irq); | 74 | struct eic *eic = get_irq_chip_data(irq); |
33 | sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq)); | 75 | eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); |
34 | } | 76 | } |
35 | 77 | ||
36 | static void eim_mask_ack_irq(unsigned int irq) | 78 | static void eic_mask_ack_irq(unsigned int irq) |
37 | { | 79 | { |
38 | struct at32_sm *sm = get_irq_chip_data(irq); | 80 | struct eic *eic = get_irq_chip_data(irq); |
39 | sm_writel(sm, EIM_ICR, 1 << (irq - sm->eim_first_irq)); | 81 | eic_writel(eic, ICR, 1 << (irq - eic->first_irq)); |
40 | sm_writel(sm, EIM_IDR, 1 << (irq - sm->eim_first_irq)); | 82 | eic_writel(eic, IDR, 1 << (irq - eic->first_irq)); |
41 | } | 83 | } |
42 | 84 | ||
43 | static void eim_unmask_irq(unsigned int irq) | 85 | static void eic_unmask_irq(unsigned int irq) |
44 | { | 86 | { |
45 | struct at32_sm *sm = get_irq_chip_data(irq); | 87 | struct eic *eic = get_irq_chip_data(irq); |
46 | sm_writel(sm, EIM_IER, 1 << (irq - sm->eim_first_irq)); | 88 | eic_writel(eic, IER, 1 << (irq - eic->first_irq)); |
47 | } | 89 | } |
48 | 90 | ||
49 | static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | 91 | static int eic_set_irq_type(unsigned int irq, unsigned int flow_type) |
50 | { | 92 | { |
51 | struct at32_sm *sm = get_irq_chip_data(irq); | 93 | struct eic *eic = get_irq_chip_data(irq); |
52 | struct irq_desc *desc; | 94 | struct irq_desc *desc; |
53 | unsigned int i = irq - sm->eim_first_irq; | 95 | unsigned int i = irq - eic->first_irq; |
54 | u32 mode, edge, level; | 96 | u32 mode, edge, level; |
55 | unsigned long flags; | ||
56 | int ret = 0; | 97 | int ret = 0; |
57 | 98 | ||
58 | flow_type &= IRQ_TYPE_SENSE_MASK; | 99 | flow_type &= IRQ_TYPE_SENSE_MASK; |
@@ -60,11 +101,10 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | |||
60 | flow_type = IRQ_TYPE_LEVEL_LOW; | 101 | flow_type = IRQ_TYPE_LEVEL_LOW; |
61 | 102 | ||
62 | desc = &irq_desc[irq]; | 103 | desc = &irq_desc[irq]; |
63 | spin_lock_irqsave(&sm->lock, flags); | ||
64 | 104 | ||
65 | mode = sm_readl(sm, EIM_MODE); | 105 | mode = eic_readl(eic, MODE); |
66 | edge = sm_readl(sm, EIM_EDGE); | 106 | edge = eic_readl(eic, EDGE); |
67 | level = sm_readl(sm, EIM_LEVEL); | 107 | level = eic_readl(eic, LEVEL); |
68 | 108 | ||
69 | switch (flow_type) { | 109 | switch (flow_type) { |
70 | case IRQ_TYPE_LEVEL_LOW: | 110 | case IRQ_TYPE_LEVEL_LOW: |
@@ -89,9 +129,9 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | |||
89 | } | 129 | } |
90 | 130 | ||
91 | if (ret == 0) { | 131 | if (ret == 0) { |
92 | sm_writel(sm, EIM_MODE, mode); | 132 | eic_writel(eic, MODE, mode); |
93 | sm_writel(sm, EIM_EDGE, edge); | 133 | eic_writel(eic, EDGE, edge); |
94 | sm_writel(sm, EIM_LEVEL, level); | 134 | eic_writel(eic, LEVEL, level); |
95 | 135 | ||
96 | if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) | 136 | if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) |
97 | flow_type |= IRQ_LEVEL; | 137 | flow_type |= IRQ_LEVEL; |
@@ -99,35 +139,33 @@ static int eim_set_irq_type(unsigned int irq, unsigned int flow_type) | |||
99 | desc->status |= flow_type; | 139 | desc->status |= flow_type; |
100 | } | 140 | } |
101 | 141 | ||
102 | spin_unlock_irqrestore(&sm->lock, flags); | ||
103 | |||
104 | return ret; | 142 | return ret; |
105 | } | 143 | } |
106 | 144 | ||
107 | struct irq_chip eim_chip = { | 145 | struct irq_chip eic_chip = { |
108 | .name = "eim", | 146 | .name = "eic", |
109 | .ack = eim_ack_irq, | 147 | .ack = eic_ack_irq, |
110 | .mask = eim_mask_irq, | 148 | .mask = eic_mask_irq, |
111 | .mask_ack = eim_mask_ack_irq, | 149 | .mask_ack = eic_mask_ack_irq, |
112 | .unmask = eim_unmask_irq, | 150 | .unmask = eic_unmask_irq, |
113 | .set_type = eim_set_irq_type, | 151 | .set_type = eic_set_irq_type, |
114 | }; | 152 | }; |
115 | 153 | ||
116 | static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) | 154 | static void demux_eic_irq(unsigned int irq, struct irq_desc *desc) |
117 | { | 155 | { |
118 | struct at32_sm *sm = desc->handler_data; | 156 | struct eic *eic = desc->handler_data; |
119 | struct irq_desc *ext_desc; | 157 | struct irq_desc *ext_desc; |
120 | unsigned long status, pending; | 158 | unsigned long status, pending; |
121 | unsigned int i, ext_irq; | 159 | unsigned int i, ext_irq; |
122 | 160 | ||
123 | status = sm_readl(sm, EIM_ISR); | 161 | status = eic_readl(eic, ISR); |
124 | pending = status & sm_readl(sm, EIM_IMR); | 162 | pending = status & eic_readl(eic, IMR); |
125 | 163 | ||
126 | while (pending) { | 164 | while (pending) { |
127 | i = fls(pending) - 1; | 165 | i = fls(pending) - 1; |
128 | pending &= ~(1 << i); | 166 | pending &= ~(1 << i); |
129 | 167 | ||
130 | ext_irq = i + sm->eim_first_irq; | 168 | ext_irq = i + eic->first_irq; |
131 | ext_desc = irq_desc + ext_irq; | 169 | ext_desc = irq_desc + ext_irq; |
132 | if (ext_desc->status & IRQ_LEVEL) | 170 | if (ext_desc->status & IRQ_LEVEL) |
133 | handle_level_irq(ext_irq, ext_desc); | 171 | handle_level_irq(ext_irq, ext_desc); |
@@ -136,51 +174,85 @@ static void demux_eim_irq(unsigned int irq, struct irq_desc *desc) | |||
136 | } | 174 | } |
137 | } | 175 | } |
138 | 176 | ||
139 | static int __init eim_init(void) | 177 | static int __init eic_probe(struct platform_device *pdev) |
140 | { | 178 | { |
141 | struct at32_sm *sm = &system_manager; | 179 | struct eic *eic; |
180 | struct resource *regs; | ||
142 | unsigned int i; | 181 | unsigned int i; |
143 | unsigned int nr_irqs; | 182 | unsigned int nr_irqs; |
144 | unsigned int int_irq; | 183 | unsigned int int_irq; |
184 | int ret; | ||
145 | u32 pattern; | 185 | u32 pattern; |
146 | 186 | ||
147 | /* | 187 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
148 | * The EIM is really the same module as SM, so register | 188 | int_irq = platform_get_irq(pdev, 0); |
149 | * mapping, etc. has been taken care of already. | 189 | if (!regs || !int_irq) { |
150 | */ | 190 | dev_dbg(&pdev->dev, "missing regs and/or irq resource\n"); |
191 | return -ENXIO; | ||
192 | } | ||
193 | |||
194 | ret = -ENOMEM; | ||
195 | eic = kzalloc(sizeof(struct eic), GFP_KERNEL); | ||
196 | if (!eic) { | ||
197 | dev_dbg(&pdev->dev, "no memory for eic structure\n"); | ||
198 | goto err_kzalloc; | ||
199 | } | ||
200 | |||
201 | eic->first_irq = EIM_IRQ_BASE + 32 * pdev->id; | ||
202 | eic->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
203 | if (!eic->regs) { | ||
204 | dev_dbg(&pdev->dev, "failed to map regs\n"); | ||
205 | goto err_ioremap; | ||
206 | } | ||
151 | 207 | ||
152 | /* | 208 | /* |
153 | * Find out how many interrupt lines that are actually | 209 | * Find out how many interrupt lines that are actually |
154 | * implemented in hardware. | 210 | * implemented in hardware. |
155 | */ | 211 | */ |
156 | sm_writel(sm, EIM_IDR, ~0UL); | 212 | eic_writel(eic, IDR, ~0UL); |
157 | sm_writel(sm, EIM_MODE, ~0UL); | 213 | eic_writel(eic, MODE, ~0UL); |
158 | pattern = sm_readl(sm, EIM_MODE); | 214 | pattern = eic_readl(eic, MODE); |
159 | nr_irqs = fls(pattern); | 215 | nr_irqs = fls(pattern); |
160 | 216 | ||
161 | /* Trigger on falling edge unless overridden by driver */ | 217 | /* Trigger on falling edge unless overridden by driver */ |
162 | sm_writel(sm, EIM_MODE, 0UL); | 218 | eic_writel(eic, MODE, 0UL); |
163 | sm_writel(sm, EIM_EDGE, 0UL); | 219 | eic_writel(eic, EDGE, 0UL); |
164 | 220 | ||
165 | sm->eim_chip = &eim_chip; | 221 | eic->chip = &eic_chip; |
166 | 222 | ||
167 | for (i = 0; i < nr_irqs; i++) { | 223 | for (i = 0; i < nr_irqs; i++) { |
168 | /* NOTE the handler we set here is ignored by the demux */ | 224 | /* NOTE the handler we set here is ignored by the demux */ |
169 | set_irq_chip_and_handler(sm->eim_first_irq + i, &eim_chip, | 225 | set_irq_chip_and_handler(eic->first_irq + i, &eic_chip, |
170 | handle_level_irq); | 226 | handle_level_irq); |
171 | set_irq_chip_data(sm->eim_first_irq + i, sm); | 227 | set_irq_chip_data(eic->first_irq + i, eic); |
172 | } | 228 | } |
173 | 229 | ||
174 | int_irq = platform_get_irq_byname(sm->pdev, "eim"); | 230 | set_irq_chained_handler(int_irq, demux_eic_irq); |
175 | 231 | set_irq_data(int_irq, eic); | |
176 | set_irq_chained_handler(int_irq, demux_eim_irq); | ||
177 | set_irq_data(int_irq, sm); | ||
178 | 232 | ||
179 | printk("EIM: External Interrupt Module at 0x%p, IRQ %u\n", | 233 | dev_info(&pdev->dev, |
180 | sm->regs, int_irq); | 234 | "External Interrupt Controller at 0x%p, IRQ %u\n", |
181 | printk("EIM: Handling %u external IRQs, starting with IRQ %u\n", | 235 | eic->regs, int_irq); |
182 | nr_irqs, sm->eim_first_irq); | 236 | dev_info(&pdev->dev, |
237 | "Handling %u external IRQs, starting with IRQ %u\n", | ||
238 | nr_irqs, eic->first_irq); | ||
183 | 239 | ||
184 | return 0; | 240 | return 0; |
241 | |||
242 | err_ioremap: | ||
243 | kfree(eic); | ||
244 | err_kzalloc: | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static struct platform_driver eic_driver = { | ||
249 | .driver = { | ||
250 | .name = "at32_eic", | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static int __init eic_init(void) | ||
255 | { | ||
256 | return platform_driver_probe(&eic_driver, eic_probe); | ||
185 | } | 257 | } |
186 | arch_initcall(eim_init); | 258 | arch_initcall(eic_init); |
diff --git a/arch/avr32/mach-at32ap/pm.h b/arch/avr32/mach-at32ap/pm.h new file mode 100644 index 000000000000..a1f8aced0a8c --- /dev/null +++ b/arch/avr32/mach-at32ap/pm.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Register definitions for the Power Manager (PM) | ||
3 | */ | ||
4 | #ifndef __ARCH_AVR32_MACH_AT32AP_PM_H__ | ||
5 | #define __ARCH_AVR32_MACH_AT32AP_PM_H__ | ||
6 | |||
7 | /* PM register offsets */ | ||
8 | #define PM_MCCTRL 0x0000 | ||
9 | #define PM_CKSEL 0x0004 | ||
10 | #define PM_CPU_MASK 0x0008 | ||
11 | #define PM_HSB_MASK 0x000c | ||
12 | #define PM_PBA_MASK 0x0010 | ||
13 | #define PM_PBB_MASK 0x0014 | ||
14 | #define PM_PLL0 0x0020 | ||
15 | #define PM_PLL1 0x0024 | ||
16 | #define PM_IER 0x0040 | ||
17 | #define PM_IDR 0x0044 | ||
18 | #define PM_IMR 0x0048 | ||
19 | #define PM_ISR 0x004c | ||
20 | #define PM_ICR 0x0050 | ||
21 | #define PM_GCCTRL(x) (0x0060 + 4 * (x)) | ||
22 | #define PM_RCAUSE 0x00c0 | ||
23 | |||
24 | /* Bitfields in CKSEL */ | ||
25 | #define PM_CPUSEL_OFFSET 0 | ||
26 | #define PM_CPUSEL_SIZE 3 | ||
27 | #define PM_CPUDIV_OFFSET 7 | ||
28 | #define PM_CPUDIV_SIZE 1 | ||
29 | #define PM_HSBSEL_OFFSET 8 | ||
30 | #define PM_HSBSEL_SIZE 3 | ||
31 | #define PM_HSBDIV_OFFSET 15 | ||
32 | #define PM_HSBDIV_SIZE 1 | ||
33 | #define PM_PBASEL_OFFSET 16 | ||
34 | #define PM_PBASEL_SIZE 3 | ||
35 | #define PM_PBADIV_OFFSET 23 | ||
36 | #define PM_PBADIV_SIZE 1 | ||
37 | #define PM_PBBSEL_OFFSET 24 | ||
38 | #define PM_PBBSEL_SIZE 3 | ||
39 | #define PM_PBBDIV_OFFSET 31 | ||
40 | #define PM_PBBDIV_SIZE 1 | ||
41 | |||
42 | /* Bitfields in PLL0 */ | ||
43 | #define PM_PLLEN_OFFSET 0 | ||
44 | #define PM_PLLEN_SIZE 1 | ||
45 | #define PM_PLLOSC_OFFSET 1 | ||
46 | #define PM_PLLOSC_SIZE 1 | ||
47 | #define PM_PLLOPT_OFFSET 2 | ||
48 | #define PM_PLLOPT_SIZE 3 | ||
49 | #define PM_PLLDIV_OFFSET 8 | ||
50 | #define PM_PLLDIV_SIZE 8 | ||
51 | #define PM_PLLMUL_OFFSET 16 | ||
52 | #define PM_PLLMUL_SIZE 8 | ||
53 | #define PM_PLLCOUNT_OFFSET 24 | ||
54 | #define PM_PLLCOUNT_SIZE 6 | ||
55 | #define PM_PLLTEST_OFFSET 31 | ||
56 | #define PM_PLLTEST_SIZE 1 | ||
57 | |||
58 | /* Bitfields in ICR */ | ||
59 | #define PM_LOCK0_OFFSET 0 | ||
60 | #define PM_LOCK0_SIZE 1 | ||
61 | #define PM_LOCK1_OFFSET 1 | ||
62 | #define PM_LOCK1_SIZE 1 | ||
63 | #define PM_WAKE_OFFSET 2 | ||
64 | #define PM_WAKE_SIZE 1 | ||
65 | #define PM_CKRDY_OFFSET 5 | ||
66 | #define PM_CKRDY_SIZE 1 | ||
67 | #define PM_MSKRDY_OFFSET 6 | ||
68 | #define PM_MSKRDY_SIZE 1 | ||
69 | |||
70 | /* Bitfields in GCCTRL0 */ | ||
71 | #define PM_OSCSEL_OFFSET 0 | ||
72 | #define PM_OSCSEL_SIZE 1 | ||
73 | #define PM_PLLSEL_OFFSET 1 | ||
74 | #define PM_PLLSEL_SIZE 1 | ||
75 | #define PM_CEN_OFFSET 2 | ||
76 | #define PM_CEN_SIZE 1 | ||
77 | #define PM_DIVEN_OFFSET 4 | ||
78 | #define PM_DIVEN_SIZE 1 | ||
79 | #define PM_DIV_OFFSET 8 | ||
80 | #define PM_DIV_SIZE 8 | ||
81 | |||
82 | /* Bitfields in RCAUSE */ | ||
83 | #define PM_POR_OFFSET 0 | ||
84 | #define PM_POR_SIZE 1 | ||
85 | #define PM_EXT_OFFSET 2 | ||
86 | #define PM_EXT_SIZE 1 | ||
87 | #define PM_WDT_OFFSET 3 | ||
88 | #define PM_WDT_SIZE 1 | ||
89 | #define PM_NTAE_OFFSET 4 | ||
90 | #define PM_NTAE_SIZE 1 | ||
91 | |||
92 | /* Bit manipulation macros */ | ||
93 | #define PM_BIT(name) \ | ||
94 | (1 << PM_##name##_OFFSET) | ||
95 | #define PM_BF(name,value) \ | ||
96 | (((value) & ((1 << PM_##name##_SIZE) - 1)) \ | ||
97 | << PM_##name##_OFFSET) | ||
98 | #define PM_BFEXT(name,value) \ | ||
99 | (((value) >> PM_##name##_OFFSET) \ | ||
100 | & ((1 << PM_##name##_SIZE) - 1)) | ||
101 | #define PM_BFINS(name,value,old)\ | ||
102 | (((old) & ~(((1 << PM_##name##_SIZE) - 1) \ | ||
103 | << PM_##name##_OFFSET)) \ | ||
104 | | PM_BF(name,value)) | ||
105 | |||
106 | /* Register access macros */ | ||
107 | #define pm_readl(reg) \ | ||
108 | __raw_readl((void __iomem *)AT32_PM_BASE + PM_##reg) | ||
109 | #define pm_writel(reg,value) \ | ||
110 | __raw_writel((value), (void __iomem *)AT32_PM_BASE + PM_##reg) | ||
111 | |||
112 | #endif /* __ARCH_AVR32_MACH_AT32AP_PM_H__ */ | ||
diff --git a/arch/avr32/mach-at32ap/sm.h b/arch/avr32/mach-at32ap/sm.h deleted file mode 100644 index cad02b512bcb..000000000000 --- a/arch/avr32/mach-at32ap/sm.h +++ /dev/null | |||
@@ -1,242 +0,0 @@ | |||
1 | /* | ||
2 | * Register definitions for SM | ||
3 | * | ||
4 | * System Manager | ||
5 | */ | ||
6 | #ifndef __ASM_AVR32_SM_H__ | ||
7 | #define __ASM_AVR32_SM_H__ | ||
8 | |||
9 | /* SM register offsets */ | ||
10 | #define SM_PM_MCCTRL 0x0000 | ||
11 | #define SM_PM_CKSEL 0x0004 | ||
12 | #define SM_PM_CPU_MASK 0x0008 | ||
13 | #define SM_PM_HSB_MASK 0x000c | ||
14 | #define SM_PM_PBA_MASK 0x0010 | ||
15 | #define SM_PM_PBB_MASK 0x0014 | ||
16 | #define SM_PM_PLL0 0x0020 | ||
17 | #define SM_PM_PLL1 0x0024 | ||
18 | #define SM_PM_VCTRL 0x0030 | ||
19 | #define SM_PM_VMREF 0x0034 | ||
20 | #define SM_PM_VMV 0x0038 | ||
21 | #define SM_PM_IER 0x0040 | ||
22 | #define SM_PM_IDR 0x0044 | ||
23 | #define SM_PM_IMR 0x0048 | ||
24 | #define SM_PM_ISR 0x004c | ||
25 | #define SM_PM_ICR 0x0050 | ||
26 | #define SM_PM_GCCTRL 0x0060 | ||
27 | #define SM_RTC_CTRL 0x0080 | ||
28 | #define SM_RTC_VAL 0x0084 | ||
29 | #define SM_RTC_TOP 0x0088 | ||
30 | #define SM_RTC_IER 0x0090 | ||
31 | #define SM_RTC_IDR 0x0094 | ||
32 | #define SM_RTC_IMR 0x0098 | ||
33 | #define SM_RTC_ISR 0x009c | ||
34 | #define SM_RTC_ICR 0x00a0 | ||
35 | #define SM_WDT_CTRL 0x00b0 | ||
36 | #define SM_WDT_CLR 0x00b4 | ||
37 | #define SM_WDT_EXT 0x00b8 | ||
38 | #define SM_RC_RCAUSE 0x00c0 | ||
39 | #define SM_EIM_IER 0x0100 | ||
40 | #define SM_EIM_IDR 0x0104 | ||
41 | #define SM_EIM_IMR 0x0108 | ||
42 | #define SM_EIM_ISR 0x010c | ||
43 | #define SM_EIM_ICR 0x0110 | ||
44 | #define SM_EIM_MODE 0x0114 | ||
45 | #define SM_EIM_EDGE 0x0118 | ||
46 | #define SM_EIM_LEVEL 0x011c | ||
47 | #define SM_EIM_TEST 0x0120 | ||
48 | #define SM_EIM_NMIC 0x0124 | ||
49 | |||
50 | /* Bitfields in PM_MCCTRL */ | ||
51 | |||
52 | /* Bitfields in PM_CKSEL */ | ||
53 | #define SM_CPUSEL_OFFSET 0 | ||
54 | #define SM_CPUSEL_SIZE 3 | ||
55 | #define SM_CPUDIV_OFFSET 7 | ||
56 | #define SM_CPUDIV_SIZE 1 | ||
57 | #define SM_HSBSEL_OFFSET 8 | ||
58 | #define SM_HSBSEL_SIZE 3 | ||
59 | #define SM_HSBDIV_OFFSET 15 | ||
60 | #define SM_HSBDIV_SIZE 1 | ||
61 | #define SM_PBASEL_OFFSET 16 | ||
62 | #define SM_PBASEL_SIZE 3 | ||
63 | #define SM_PBADIV_OFFSET 23 | ||
64 | #define SM_PBADIV_SIZE 1 | ||
65 | #define SM_PBBSEL_OFFSET 24 | ||
66 | #define SM_PBBSEL_SIZE 3 | ||
67 | #define SM_PBBDIV_OFFSET 31 | ||
68 | #define SM_PBBDIV_SIZE 1 | ||
69 | |||
70 | /* Bitfields in PM_CPU_MASK */ | ||
71 | |||
72 | /* Bitfields in PM_HSB_MASK */ | ||
73 | |||
74 | /* Bitfields in PM_PBA_MASK */ | ||
75 | |||
76 | /* Bitfields in PM_PBB_MASK */ | ||
77 | |||
78 | /* Bitfields in PM_PLL0 */ | ||
79 | #define SM_PLLEN_OFFSET 0 | ||
80 | #define SM_PLLEN_SIZE 1 | ||
81 | #define SM_PLLOSC_OFFSET 1 | ||
82 | #define SM_PLLOSC_SIZE 1 | ||
83 | #define SM_PLLOPT_OFFSET 2 | ||
84 | #define SM_PLLOPT_SIZE 3 | ||
85 | #define SM_PLLDIV_OFFSET 8 | ||
86 | #define SM_PLLDIV_SIZE 8 | ||
87 | #define SM_PLLMUL_OFFSET 16 | ||
88 | #define SM_PLLMUL_SIZE 8 | ||
89 | #define SM_PLLCOUNT_OFFSET 24 | ||
90 | #define SM_PLLCOUNT_SIZE 6 | ||
91 | #define SM_PLLTEST_OFFSET 31 | ||
92 | #define SM_PLLTEST_SIZE 1 | ||
93 | |||
94 | /* Bitfields in PM_PLL1 */ | ||
95 | |||
96 | /* Bitfields in PM_VCTRL */ | ||
97 | #define SM_VAUTO_OFFSET 0 | ||
98 | #define SM_VAUTO_SIZE 1 | ||
99 | #define SM_PM_VCTRL_VAL_OFFSET 8 | ||
100 | #define SM_PM_VCTRL_VAL_SIZE 7 | ||
101 | |||
102 | /* Bitfields in PM_VMREF */ | ||
103 | #define SM_REFSEL_OFFSET 0 | ||
104 | #define SM_REFSEL_SIZE 4 | ||
105 | |||
106 | /* Bitfields in PM_VMV */ | ||
107 | #define SM_PM_VMV_VAL_OFFSET 0 | ||
108 | #define SM_PM_VMV_VAL_SIZE 8 | ||
109 | |||
110 | /* Bitfields in PM_IER */ | ||
111 | |||
112 | /* Bitfields in PM_IDR */ | ||
113 | |||
114 | /* Bitfields in PM_IMR */ | ||
115 | |||
116 | /* Bitfields in PM_ISR */ | ||
117 | |||
118 | /* Bitfields in PM_ICR */ | ||
119 | #define SM_LOCK0_OFFSET 0 | ||
120 | #define SM_LOCK0_SIZE 1 | ||
121 | #define SM_LOCK1_OFFSET 1 | ||
122 | #define SM_LOCK1_SIZE 1 | ||
123 | #define SM_WAKE_OFFSET 2 | ||
124 | #define SM_WAKE_SIZE 1 | ||
125 | #define SM_VOK_OFFSET 3 | ||
126 | #define SM_VOK_SIZE 1 | ||
127 | #define SM_VMRDY_OFFSET 4 | ||
128 | #define SM_VMRDY_SIZE 1 | ||
129 | #define SM_CKRDY_OFFSET 5 | ||
130 | #define SM_CKRDY_SIZE 1 | ||
131 | |||
132 | /* Bitfields in PM_GCCTRL */ | ||
133 | #define SM_OSCSEL_OFFSET 0 | ||
134 | #define SM_OSCSEL_SIZE 1 | ||
135 | #define SM_PLLSEL_OFFSET 1 | ||
136 | #define SM_PLLSEL_SIZE 1 | ||
137 | #define SM_CEN_OFFSET 2 | ||
138 | #define SM_CEN_SIZE 1 | ||
139 | #define SM_CPC_OFFSET 3 | ||
140 | #define SM_CPC_SIZE 1 | ||
141 | #define SM_DIVEN_OFFSET 4 | ||
142 | #define SM_DIVEN_SIZE 1 | ||
143 | #define SM_DIV_OFFSET 8 | ||
144 | #define SM_DIV_SIZE 8 | ||
145 | |||
146 | /* Bitfields in RTC_CTRL */ | ||
147 | #define SM_PCLR_OFFSET 1 | ||
148 | #define SM_PCLR_SIZE 1 | ||
149 | #define SM_TOPEN_OFFSET 2 | ||
150 | #define SM_TOPEN_SIZE 1 | ||
151 | #define SM_CLKEN_OFFSET 3 | ||
152 | #define SM_CLKEN_SIZE 1 | ||
153 | #define SM_PSEL_OFFSET 8 | ||
154 | #define SM_PSEL_SIZE 16 | ||
155 | |||
156 | /* Bitfields in RTC_VAL */ | ||
157 | #define SM_RTC_VAL_VAL_OFFSET 0 | ||
158 | #define SM_RTC_VAL_VAL_SIZE 31 | ||
159 | |||
160 | /* Bitfields in RTC_TOP */ | ||
161 | #define SM_RTC_TOP_VAL_OFFSET 0 | ||
162 | #define SM_RTC_TOP_VAL_SIZE 32 | ||
163 | |||
164 | /* Bitfields in RTC_IER */ | ||
165 | |||
166 | /* Bitfields in RTC_IDR */ | ||
167 | |||
168 | /* Bitfields in RTC_IMR */ | ||
169 | |||
170 | /* Bitfields in RTC_ISR */ | ||
171 | |||
172 | /* Bitfields in RTC_ICR */ | ||
173 | #define SM_TOPI_OFFSET 0 | ||
174 | #define SM_TOPI_SIZE 1 | ||
175 | |||
176 | /* Bitfields in WDT_CTRL */ | ||
177 | #define SM_KEY_OFFSET 24 | ||
178 | #define SM_KEY_SIZE 8 | ||
179 | |||
180 | /* Bitfields in WDT_CLR */ | ||
181 | |||
182 | /* Bitfields in WDT_EXT */ | ||
183 | |||
184 | /* Bitfields in RC_RCAUSE */ | ||
185 | #define SM_POR_OFFSET 0 | ||
186 | #define SM_POR_SIZE 1 | ||
187 | #define SM_BOD_OFFSET 1 | ||
188 | #define SM_BOD_SIZE 1 | ||
189 | #define SM_EXT_OFFSET 2 | ||
190 | #define SM_EXT_SIZE 1 | ||
191 | #define SM_WDT_OFFSET 3 | ||
192 | #define SM_WDT_SIZE 1 | ||
193 | #define SM_NTAE_OFFSET 4 | ||
194 | #define SM_NTAE_SIZE 1 | ||
195 | #define SM_SERP_OFFSET 5 | ||
196 | #define SM_SERP_SIZE 1 | ||
197 | |||
198 | /* Bitfields in EIM_IER */ | ||
199 | |||
200 | /* Bitfields in EIM_IDR */ | ||
201 | |||
202 | /* Bitfields in EIM_IMR */ | ||
203 | |||
204 | /* Bitfields in EIM_ISR */ | ||
205 | |||
206 | /* Bitfields in EIM_ICR */ | ||
207 | |||
208 | /* Bitfields in EIM_MODE */ | ||
209 | |||
210 | /* Bitfields in EIM_EDGE */ | ||
211 | #define SM_INT0_OFFSET 0 | ||
212 | #define SM_INT0_SIZE 1 | ||
213 | #define SM_INT1_OFFSET 1 | ||
214 | #define SM_INT1_SIZE 1 | ||
215 | #define SM_INT2_OFFSET 2 | ||
216 | #define SM_INT2_SIZE 1 | ||
217 | #define SM_INT3_OFFSET 3 | ||
218 | #define SM_INT3_SIZE 1 | ||
219 | |||
220 | /* Bitfields in EIM_LEVEL */ | ||
221 | |||
222 | /* Bitfields in EIM_TEST */ | ||
223 | #define SM_TESTEN_OFFSET 31 | ||
224 | #define SM_TESTEN_SIZE 1 | ||
225 | |||
226 | /* Bitfields in EIM_NMIC */ | ||
227 | #define SM_EN_OFFSET 0 | ||
228 | #define SM_EN_SIZE 1 | ||
229 | |||
230 | /* Bit manipulation macros */ | ||
231 | #define SM_BIT(name) (1 << SM_##name##_OFFSET) | ||
232 | #define SM_BF(name,value) (((value) & ((1 << SM_##name##_SIZE) - 1)) << SM_##name##_OFFSET) | ||
233 | #define SM_BFEXT(name,value) (((value) >> SM_##name##_OFFSET) & ((1 << SM_##name##_SIZE) - 1)) | ||
234 | #define SM_BFINS(name,value,old) (((old) & ~(((1 << SM_##name##_SIZE) - 1) << SM_##name##_OFFSET)) | SM_BF(name,value)) | ||
235 | |||
236 | /* Register access macros */ | ||
237 | #define sm_readl(port,reg) \ | ||
238 | __raw_readl((port)->regs + SM_##reg) | ||
239 | #define sm_writel(port,reg,value) \ | ||
240 | __raw_writel((value), (port)->regs + SM_##reg) | ||
241 | |||
242 | #endif /* __ASM_AVR32_SM_H__ */ | ||
diff --git a/include/asm-avr32/arch-at32ap/board.h b/include/asm-avr32/arch-at32ap/board.h index 974480438849..0215965dc586 100644 --- a/include/asm-avr32/arch-at32ap/board.h +++ b/include/asm-avr32/arch-at32ap/board.h | |||
@@ -36,4 +36,18 @@ struct platform_device * | |||
36 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, | 36 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, |
37 | unsigned long fbmem_start, unsigned long fbmem_len); | 37 | unsigned long fbmem_start, unsigned long fbmem_len); |
38 | 38 | ||
39 | /* depending on what's hooked up, not all SSC pins will be used */ | ||
40 | #define ATMEL_SSC_TK 0x01 | ||
41 | #define ATMEL_SSC_TF 0x02 | ||
42 | #define ATMEL_SSC_TD 0x04 | ||
43 | #define ATMEL_SSC_TX (ATMEL_SSC_TK | ATMEL_SSC_TF | ATMEL_SSC_TD) | ||
44 | |||
45 | #define ATMEL_SSC_RK 0x10 | ||
46 | #define ATMEL_SSC_RF 0x20 | ||
47 | #define ATMEL_SSC_RD 0x40 | ||
48 | #define ATMEL_SSC_RX (ATMEL_SSC_RK | ATMEL_SSC_RF | ATMEL_SSC_RD) | ||
49 | |||
50 | struct platform_device * | ||
51 | at32_add_device_ssc(unsigned int id, unsigned int flags); | ||
52 | |||
39 | #endif /* __ASM_ARCH_BOARD_H */ | 53 | #endif /* __ASM_ARCH_BOARD_H */ |
diff --git a/include/asm-avr32/arch-at32ap/sm.h b/include/asm-avr32/arch-at32ap/sm.h deleted file mode 100644 index 265a9ead20bf..000000000000 --- a/include/asm-avr32/arch-at32ap/sm.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * AT32 System Manager interface. | ||
3 | * | ||
4 | * Copyright (C) 2006 Atmel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | #ifndef __ASM_AVR32_AT32_SM_H__ | ||
11 | #define __ASM_AVR32_AT32_SM_H__ | ||
12 | |||
13 | struct irq_chip; | ||
14 | struct platform_device; | ||
15 | |||
16 | struct at32_sm { | ||
17 | spinlock_t lock; | ||
18 | void __iomem *regs; | ||
19 | struct irq_chip *eim_chip; | ||
20 | unsigned int eim_first_irq; | ||
21 | struct platform_device *pdev; | ||
22 | }; | ||
23 | |||
24 | extern struct platform_device at32_sm_device; | ||
25 | extern struct at32_sm system_manager; | ||
26 | |||
27 | #endif /* __ASM_AVR32_AT32_SM_H__ */ | ||
diff --git a/include/asm-avr32/atomic.h b/include/asm-avr32/atomic.h index b9c2548a52f3..7ef3862a73d0 100644 --- a/include/asm-avr32/atomic.h +++ b/include/asm-avr32/atomic.h | |||
@@ -101,7 +101,7 @@ static inline int atomic_sub_unless(atomic_t *v, int a, int u) | |||
101 | " mov %1, 1\n" | 101 | " mov %1, 1\n" |
102 | "1:" | 102 | "1:" |
103 | : "=&r"(tmp), "=&r"(result), "=o"(v->counter) | 103 | : "=&r"(tmp), "=&r"(result), "=o"(v->counter) |
104 | : "m"(v->counter), "rKs21"(a), "rKs21"(u) | 104 | : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result) |
105 | : "cc", "memory"); | 105 | : "cc", "memory"); |
106 | 106 | ||
107 | return result; | 107 | return result; |
@@ -137,7 +137,7 @@ static inline int atomic_add_unless(atomic_t *v, int a, int u) | |||
137 | " mov %1, 1\n" | 137 | " mov %1, 1\n" |
138 | "1:" | 138 | "1:" |
139 | : "=&r"(tmp), "=&r"(result), "=o"(v->counter) | 139 | : "=&r"(tmp), "=&r"(result), "=o"(v->counter) |
140 | : "m"(v->counter), "r"(a), "ir"(u) | 140 | : "m"(v->counter), "r"(a), "ir"(u), "1"(result) |
141 | : "cc", "memory"); | 141 | : "cc", "memory"); |
142 | } | 142 | } |
143 | 143 | ||
diff --git a/include/asm-avr32/unaligned.h b/include/asm-avr32/unaligned.h index 3042723fcbfd..36f5fd430543 100644 --- a/include/asm-avr32/unaligned.h +++ b/include/asm-avr32/unaligned.h | |||
@@ -7,19 +7,10 @@ | |||
7 | * words, but halfwords must be halfword-aligned, and doublewords must | 7 | * words, but halfwords must be halfword-aligned, and doublewords must |
8 | * be word-aligned. | 8 | * be word-aligned. |
9 | * | 9 | * |
10 | * TODO: Make all this CPU-specific and optimize. | 10 | * However, swapped word loads must be word-aligned so we can't |
11 | * optimize word loads in general. | ||
11 | */ | 12 | */ |
12 | 13 | ||
13 | #include <linux/string.h> | 14 | #include <asm-generic/unaligned.h> |
14 | |||
15 | /* Use memmove here, so gcc does not insert a __builtin_memcpy. */ | ||
16 | |||
17 | #define get_unaligned(ptr) \ | ||
18 | ({ __typeof__(*(ptr)) __tmp; memmove(&__tmp, (ptr), sizeof(*(ptr))); __tmp; }) | ||
19 | |||
20 | #define put_unaligned(val, ptr) \ | ||
21 | ({ __typeof__(*(ptr)) __tmp = (val); \ | ||
22 | memmove((ptr), &__tmp, sizeof(*(ptr))); \ | ||
23 | (void)0; }) | ||
24 | 15 | ||
25 | #endif /* __ASM_AVR32_UNALIGNED_H */ | 16 | #endif /* __ASM_AVR32_UNALIGNED_H */ |