diff options
Diffstat (limited to 'arch/arm/mach-at91rm9200')
-rw-r--r-- | arch/arm/mach-at91rm9200/Kconfig | 12 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/Makefile | 17 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-carmeva.c | 131 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-csb337.c | 45 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-csb637.c | 32 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-dk.c | 59 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-eb9200.c | 130 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-ek.c | 49 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-kafa.c | 116 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/board-kb9202.c | 125 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/clock.c | 126 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/common.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/devices.c | 406 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/generic.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/gpio.c | 89 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/irq.c | 44 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/pm.c | 225 | ||||
-rw-r--r-- | arch/arm/mach-at91rm9200/time.c | 57 |
18 files changed, 1533 insertions, 156 deletions
diff --git a/arch/arm/mach-at91rm9200/Kconfig b/arch/arm/mach-at91rm9200/Kconfig index 4b7218fc3eb1..1ab5b7828318 100644 --- a/arch/arm/mach-at91rm9200/Kconfig +++ b/arch/arm/mach-at91rm9200/Kconfig | |||
@@ -40,6 +40,18 @@ config MACH_KB9200 | |||
40 | help | 40 | help |
41 | Select this if you are using KwikByte's KB920x board | 41 | Select this if you are using KwikByte's KB920x board |
42 | 42 | ||
43 | config MACH_ATEB9200 | ||
44 | bool "Embest's ATEB9200" | ||
45 | depends on ARCH_AT91RM9200 | ||
46 | help | ||
47 | Select this if you are using Embest's ATEB9200 board | ||
48 | |||
49 | config MACH_KAFA | ||
50 | bool "Sperry-Sun KAFA board" | ||
51 | depends on ARCH_AT91RM9200 | ||
52 | help | ||
53 | Select this if you are using Sperry-Sun's KAFA board | ||
54 | |||
43 | 55 | ||
44 | comment "AT91RM9200 Feature Selections" | 56 | comment "AT91RM9200 Feature Selections" |
45 | 57 | ||
diff --git a/arch/arm/mach-at91rm9200/Makefile b/arch/arm/mach-at91rm9200/Makefile index ef88c4128edc..81ebc6684ad2 100644 --- a/arch/arm/mach-at91rm9200/Makefile +++ b/arch/arm/mach-at91rm9200/Makefile | |||
@@ -7,22 +7,31 @@ obj-m := | |||
7 | obj-n := | 7 | obj-n := |
8 | obj- := | 8 | obj- := |
9 | 9 | ||
10 | obj-$(CONFIG_PM) += pm.o | ||
11 | |||
10 | # Board-specific support | 12 | # Board-specific support |
11 | obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o | 13 | obj-$(CONFIG_ARCH_AT91RM9200DK) += board-dk.o |
12 | obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o | 14 | obj-$(CONFIG_MACH_AT91RM9200EK) += board-ek.o |
13 | obj-$(CONFIG_MACH_CSB337) += board-csb337.o | 15 | obj-$(CONFIG_MACH_CSB337) += board-csb337.o |
14 | obj-$(CONFIG_MACH_CSB637) += board-csb637.o | 16 | obj-$(CONFIG_MACH_CSB637) += board-csb637.o |
15 | #obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o | 17 | obj-$(CONFIG_MACH_CARMEVA) += board-carmeva.o |
16 | #obj-$(CONFIG_MACH_KB9200) += board-kb9202.o | 18 | obj-$(CONFIG_MACH_KB9200) += board-kb9202.o |
19 | obj-$(CONFIG_MACH_ATEB9200) += board-eb9200.o | ||
20 | obj-$(CONFIG_MACH_KAFA) += board-kafa.o | ||
17 | 21 | ||
18 | # LEDs support | 22 | # LEDs support |
19 | led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o | 23 | led-$(CONFIG_ARCH_AT91RM9200DK) += leds.o |
20 | led-$(CONFIG_MACH_AT91RM9200EK) += leds.o | 24 | led-$(CONFIG_MACH_AT91RM9200EK) += leds.o |
21 | led-$(CONFIG_MACH_CSB337) += leds.o | 25 | led-$(CONFIG_MACH_CSB337) += leds.o |
22 | led-$(CONFIG_MACH_CSB637) += leds.o | 26 | led-$(CONFIG_MACH_CSB637) += leds.o |
23 | #led-$(CONFIG_MACH_KB9200) += leds.o | 27 | led-$(CONFIG_MACH_KB9200) += leds.o |
24 | #led-$(CONFIG_MACH_KAFA) += leds.o | 28 | led-$(CONFIG_MACH_KAFA) += leds.o |
25 | obj-$(CONFIG_LEDS) += $(led-y) | 29 | obj-$(CONFIG_LEDS) += $(led-y) |
26 | 30 | ||
27 | # VGA support | 31 | # VGA support |
28 | #obj-$(CONFIG_FB_S1D13XXX) += ics1523.o | 32 | #obj-$(CONFIG_FB_S1D13XXX) += ics1523.o |
33 | |||
34 | |||
35 | ifeq ($(CONFIG_PM_DEBUG),y) | ||
36 | CFLAGS_pm.o += -DDEBUG | ||
37 | endif | ||
diff --git a/arch/arm/mach-at91rm9200/board-carmeva.c b/arch/arm/mach-at91rm9200/board-carmeva.c new file mode 100644 index 000000000000..2c138b542ebe --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-carmeva.c | |||
@@ -0,0 +1,131 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-at91rm9200/board-carmeva.c | ||
3 | * | ||
4 | * Copyright (c) 2005 Peer Georgi | ||
5 | * Conitec Datasystems | ||
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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/setup.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <asm/irq.h> | ||
33 | |||
34 | #include <asm/mach/arch.h> | ||
35 | #include <asm/mach/map.h> | ||
36 | #include <asm/mach/irq.h> | ||
37 | |||
38 | #include <asm/hardware.h> | ||
39 | #include <asm/arch/board.h> | ||
40 | #include <asm/arch/gpio.h> | ||
41 | |||
42 | #include "generic.h" | ||
43 | |||
44 | static void __init carmeva_init_irq(void) | ||
45 | { | ||
46 | /* Initialize AIC controller */ | ||
47 | at91rm9200_init_irq(NULL); | ||
48 | |||
49 | /* Set up the GPIO interrupts */ | ||
50 | at91_gpio_irq_setup(BGA_GPIO_BANKS); | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Serial port configuration. | ||
55 | * 0 .. 3 = USART0 .. USART3 | ||
56 | * 4 = DBGU | ||
57 | */ | ||
58 | static struct at91_uart_config __initdata carmeva_uart_config = { | ||
59 | .console_tty = 0, /* ttyS0 */ | ||
60 | .nr_tty = 2, | ||
61 | .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
62 | }; | ||
63 | |||
64 | static void __init carmeva_map_io(void) | ||
65 | { | ||
66 | at91rm9200_map_io(); | ||
67 | |||
68 | /* Initialize clocks: 20.000 MHz crystal */ | ||
69 | at91_clock_init(20000000); | ||
70 | |||
71 | /* Setup the serial ports and console */ | ||
72 | at91_init_serial(&carmeva_uart_config); | ||
73 | } | ||
74 | |||
75 | static struct at91_eth_data __initdata carmeva_eth_data = { | ||
76 | .phy_irq_pin = AT91_PIN_PC4, | ||
77 | .is_rmii = 1, | ||
78 | }; | ||
79 | |||
80 | static struct at91_usbh_data __initdata carmeva_usbh_data = { | ||
81 | .ports = 2, | ||
82 | }; | ||
83 | |||
84 | static struct at91_udc_data __initdata carmeva_udc_data = { | ||
85 | .vbus_pin = AT91_PIN_PD12, | ||
86 | .pullup_pin = AT91_PIN_PD9, | ||
87 | }; | ||
88 | |||
89 | /* FIXME: user dependend */ | ||
90 | // static struct at91_cf_data __initdata carmeva_cf_data = { | ||
91 | // .det_pin = AT91_PIN_PB0, | ||
92 | // .rst_pin = AT91_PIN_PC5, | ||
93 | // .irq_pin = ... not connected | ||
94 | // .vcc_pin = ... always powered | ||
95 | // }; | ||
96 | |||
97 | static struct at91_mmc_data __initdata carmeva_mmc_data = { | ||
98 | .is_b = 0, | ||
99 | .wire4 = 1, | ||
100 | }; | ||
101 | |||
102 | static void __init carmeva_board_init(void) | ||
103 | { | ||
104 | /* Serial */ | ||
105 | at91_add_device_serial(); | ||
106 | /* Ethernet */ | ||
107 | at91_add_device_eth(&carmeva_eth_data); | ||
108 | /* USB Host */ | ||
109 | at91_add_device_usbh(&carmeva_usbh_data); | ||
110 | /* USB Device */ | ||
111 | at91_add_device_udc(&carmeva_udc_data); | ||
112 | /* I2C */ | ||
113 | at91_add_device_i2c(); | ||
114 | /* Compact Flash */ | ||
115 | // at91_add_device_cf(&carmeva_cf_data); | ||
116 | /* SPI */ | ||
117 | // at91_add_device_spi(NULL, 0); | ||
118 | /* MMC */ | ||
119 | at91_add_device_mmc(&carmeva_mmc_data); | ||
120 | } | ||
121 | |||
122 | MACHINE_START(CARMEVA, "Carmeva") | ||
123 | /* Maintainer: Conitec Datasystems */ | ||
124 | .phys_io = AT91_BASE_SYS, | ||
125 | .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, | ||
126 | .boot_params = AT91_SDRAM_BASE + 0x100, | ||
127 | .timer = &at91rm9200_timer, | ||
128 | .map_io = carmeva_map_io, | ||
129 | .init_irq = carmeva_init_irq, | ||
130 | .init_machine = carmeva_board_init, | ||
131 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91rm9200/board-csb337.c b/arch/arm/mach-at91rm9200/board-csb337.c index f45104ceea8f..e94645d77f7a 100644 --- a/arch/arm/mach-at91rm9200/board-csb337.c +++ b/arch/arm/mach-at91rm9200/board-csb337.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/mm.h> | 24 | #include <linux/mm.h> |
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/spi/spi.h> | ||
27 | 28 | ||
28 | #include <asm/hardware.h> | 29 | #include <asm/hardware.h> |
29 | #include <asm/setup.h> | 30 | #include <asm/setup.h> |
@@ -34,9 +35,9 @@ | |||
34 | #include <asm/mach/map.h> | 35 | #include <asm/mach/map.h> |
35 | #include <asm/mach/irq.h> | 36 | #include <asm/mach/irq.h> |
36 | 37 | ||
37 | #include <asm/arch/hardware.h> | 38 | #include <asm/hardware.h> |
38 | #include <asm/mach/serial_at91rm9200.h> | ||
39 | #include <asm/arch/board.h> | 39 | #include <asm/arch/board.h> |
40 | #include <asm/arch/gpio.h> | ||
40 | 41 | ||
41 | #include "generic.h" | 42 | #include "generic.h" |
42 | 43 | ||
@@ -54,32 +55,24 @@ static void __init csb337_init_irq(void) | |||
54 | * 0 .. 3 = USART0 .. USART3 | 55 | * 0 .. 3 = USART0 .. USART3 |
55 | * 4 = DBGU | 56 | * 4 = DBGU |
56 | */ | 57 | */ |
57 | #define CSB337_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | 58 | static struct at91_uart_config __initdata csb337_uart_config = { |
58 | #define CSB337_SERIAL_CONSOLE 0 /* ttyS0 */ | 59 | .console_tty = 0, /* ttyS0 */ |
60 | .nr_tty = 2, | ||
61 | .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
62 | }; | ||
59 | 63 | ||
60 | static void __init csb337_map_io(void) | 64 | static void __init csb337_map_io(void) |
61 | { | 65 | { |
62 | int serial[AT91_NR_UART] = CSB337_UART_MAP; | ||
63 | int i; | ||
64 | |||
65 | at91rm9200_map_io(); | 66 | at91rm9200_map_io(); |
66 | 67 | ||
67 | /* Initialize clocks: 3.6864 MHz crystal */ | 68 | /* Initialize clocks: 3.6864 MHz crystal */ |
68 | at91_clock_init(3686400); | 69 | at91_clock_init(3686400); |
69 | 70 | ||
70 | /* Setup the LEDs */ | 71 | /* Setup the LEDs */ |
71 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); | 72 | at91_init_leds(AT91_PIN_PB0, AT91_PIN_PB1); |
72 | 73 | ||
73 | #ifdef CONFIG_SERIAL_AT91 | 74 | /* Setup the serial ports and console */ |
74 | at91_console_port = CSB337_SERIAL_CONSOLE; | 75 | at91_init_serial(&csb337_uart_config); |
75 | memcpy(at91_serial_map, serial, sizeof(serial)); | ||
76 | |||
77 | /* Register UARTs */ | ||
78 | for (i = 0; i < AT91_NR_UART; i++) { | ||
79 | if (serial[i] >= 0) | ||
80 | at91_register_uart(i, serial[i]); | ||
81 | } | ||
82 | #endif | ||
83 | } | 76 | } |
84 | 77 | ||
85 | static struct at91_eth_data __initdata csb337_eth_data = { | 78 | static struct at91_eth_data __initdata csb337_eth_data = { |
@@ -118,17 +111,31 @@ static struct at91_mmc_data __initdata csb337_mmc_data = { | |||
118 | .wp_pin = AT91_PIN_PD6, | 111 | .wp_pin = AT91_PIN_PD6, |
119 | }; | 112 | }; |
120 | 113 | ||
114 | static struct spi_board_info csb337_spi_devices[] = { | ||
115 | { /* CAN controller */ | ||
116 | .modalias = "sak82c900", | ||
117 | .chip_select = 0, | ||
118 | .max_speed_hz = 6 * 1000 * 1000, | ||
119 | }, | ||
120 | }; | ||
121 | |||
121 | static void __init csb337_board_init(void) | 122 | static void __init csb337_board_init(void) |
122 | { | 123 | { |
124 | /* Serial */ | ||
125 | at91_add_device_serial(); | ||
123 | /* Ethernet */ | 126 | /* Ethernet */ |
124 | at91_add_device_eth(&csb337_eth_data); | 127 | at91_add_device_eth(&csb337_eth_data); |
125 | /* USB Host */ | 128 | /* USB Host */ |
126 | at91_add_device_usbh(&csb337_usbh_data); | 129 | at91_add_device_usbh(&csb337_usbh_data); |
127 | /* USB Device */ | 130 | /* USB Device */ |
128 | at91_add_device_udc(&csb337_udc_data); | 131 | at91_add_device_udc(&csb337_udc_data); |
132 | /* I2C */ | ||
133 | at91_add_device_i2c(); | ||
129 | /* Compact Flash */ | 134 | /* Compact Flash */ |
130 | at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ | 135 | at91_set_gpio_input(AT91_PIN_PB22, 1); /* IOIS16 */ |
131 | at91_add_device_cf(&csb337_cf_data); | 136 | at91_add_device_cf(&csb337_cf_data); |
137 | /* SPI */ | ||
138 | at91_add_device_spi(csb337_spi_devices, ARRAY_SIZE(csb337_spi_devices)); | ||
132 | /* MMC */ | 139 | /* MMC */ |
133 | at91_add_device_mmc(&csb337_mmc_data); | 140 | at91_add_device_mmc(&csb337_mmc_data); |
134 | } | 141 | } |
diff --git a/arch/arm/mach-at91rm9200/board-csb637.c b/arch/arm/mach-at91rm9200/board-csb637.c index f2c2d6e79bc6..67d5f7786cdb 100644 --- a/arch/arm/mach-at91rm9200/board-csb637.c +++ b/arch/arm/mach-at91rm9200/board-csb637.c | |||
@@ -34,9 +34,9 @@ | |||
34 | #include <asm/mach/map.h> | 34 | #include <asm/mach/map.h> |
35 | #include <asm/mach/irq.h> | 35 | #include <asm/mach/irq.h> |
36 | 36 | ||
37 | #include <asm/arch/hardware.h> | 37 | #include <asm/hardware.h> |
38 | #include <asm/mach/serial_at91rm9200.h> | ||
39 | #include <asm/arch/board.h> | 38 | #include <asm/arch/board.h> |
39 | #include <asm/arch/gpio.h> | ||
40 | 40 | ||
41 | #include "generic.h" | 41 | #include "generic.h" |
42 | 42 | ||
@@ -54,14 +54,14 @@ static void __init csb637_init_irq(void) | |||
54 | * 0 .. 3 = USART0 .. USART3 | 54 | * 0 .. 3 = USART0 .. USART3 |
55 | * 4 = DBGU | 55 | * 4 = DBGU |
56 | */ | 56 | */ |
57 | #define CSB637_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | 57 | static struct at91_uart_config __initdata csb637_uart_config = { |
58 | #define CSB637_SERIAL_CONSOLE 0 /* ttyS0 */ | 58 | .console_tty = 0, /* ttyS0 */ |
59 | .nr_tty = 2, | ||
60 | .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
61 | }; | ||
59 | 62 | ||
60 | static void __init csb637_map_io(void) | 63 | static void __init csb637_map_io(void) |
61 | { | 64 | { |
62 | int serial[AT91_NR_UART] = CSB637_UART_MAP; | ||
63 | int i; | ||
64 | |||
65 | at91rm9200_map_io(); | 65 | at91rm9200_map_io(); |
66 | 66 | ||
67 | /* Initialize clocks: 3.6864 MHz crystal */ | 67 | /* Initialize clocks: 3.6864 MHz crystal */ |
@@ -70,16 +70,8 @@ static void __init csb637_map_io(void) | |||
70 | /* Setup the LEDs */ | 70 | /* Setup the LEDs */ |
71 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); | 71 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); |
72 | 72 | ||
73 | #ifdef CONFIG_SERIAL_AT91 | 73 | /* Setup the serial ports and console */ |
74 | at91_console_port = CSB637_SERIAL_CONSOLE; | 74 | at91_init_serial(&csb637_uart_config); |
75 | memcpy(at91_serial_map, serial, sizeof(serial)); | ||
76 | |||
77 | /* Register UARTs */ | ||
78 | for (i = 0; i < AT91_NR_UART; i++) { | ||
79 | if (serial[i] >= 0) | ||
80 | at91_register_uart(i, serial[i]); | ||
81 | } | ||
82 | #endif | ||
83 | } | 75 | } |
84 | 76 | ||
85 | static struct at91_eth_data __initdata csb637_eth_data = { | 77 | static struct at91_eth_data __initdata csb637_eth_data = { |
@@ -98,12 +90,18 @@ static struct at91_udc_data __initdata csb637_udc_data = { | |||
98 | 90 | ||
99 | static void __init csb637_board_init(void) | 91 | static void __init csb637_board_init(void) |
100 | { | 92 | { |
93 | /* Serial */ | ||
94 | at91_add_device_serial(); | ||
101 | /* Ethernet */ | 95 | /* Ethernet */ |
102 | at91_add_device_eth(&csb637_eth_data); | 96 | at91_add_device_eth(&csb637_eth_data); |
103 | /* USB Host */ | 97 | /* USB Host */ |
104 | at91_add_device_usbh(&csb637_usbh_data); | 98 | at91_add_device_usbh(&csb637_usbh_data); |
105 | /* USB Device */ | 99 | /* USB Device */ |
106 | at91_add_device_udc(&csb637_udc_data); | 100 | at91_add_device_udc(&csb637_udc_data); |
101 | /* I2C */ | ||
102 | at91_add_device_i2c(); | ||
103 | /* SPI */ | ||
104 | at91_add_device_spi(NULL, 0); | ||
107 | } | 105 | } |
108 | 106 | ||
109 | MACHINE_START(CSB637, "Cogent CSB637") | 107 | MACHINE_START(CSB637, "Cogent CSB637") |
diff --git a/arch/arm/mach-at91rm9200/board-dk.c b/arch/arm/mach-at91rm9200/board-dk.c index 2d7200ed66ed..48d7390fa584 100644 --- a/arch/arm/mach-at91rm9200/board-dk.c +++ b/arch/arm/mach-at91rm9200/board-dk.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/spi/spi.h> | ||
30 | 31 | ||
31 | #include <asm/hardware.h> | 32 | #include <asm/hardware.h> |
32 | #include <asm/setup.h> | 33 | #include <asm/setup.h> |
@@ -37,9 +38,9 @@ | |||
37 | #include <asm/mach/map.h> | 38 | #include <asm/mach/map.h> |
38 | #include <asm/mach/irq.h> | 39 | #include <asm/mach/irq.h> |
39 | 40 | ||
40 | #include <asm/arch/hardware.h> | 41 | #include <asm/hardware.h> |
41 | #include <asm/mach/serial_at91rm9200.h> | ||
42 | #include <asm/arch/board.h> | 42 | #include <asm/arch/board.h> |
43 | #include <asm/arch/gpio.h> | ||
43 | 44 | ||
44 | #include "generic.h" | 45 | #include "generic.h" |
45 | 46 | ||
@@ -57,14 +58,14 @@ static void __init dk_init_irq(void) | |||
57 | * 0 .. 3 = USART0 .. USART3 | 58 | * 0 .. 3 = USART0 .. USART3 |
58 | * 4 = DBGU | 59 | * 4 = DBGU |
59 | */ | 60 | */ |
60 | #define DK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | 61 | static struct at91_uart_config __initdata dk_uart_config = { |
61 | #define DK_SERIAL_CONSOLE 0 /* ttyS0 */ | 62 | .console_tty = 0, /* ttyS0 */ |
63 | .nr_tty = 2, | ||
64 | .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
65 | }; | ||
62 | 66 | ||
63 | static void __init dk_map_io(void) | 67 | static void __init dk_map_io(void) |
64 | { | 68 | { |
65 | int serial[AT91_NR_UART] = DK_UART_MAP; | ||
66 | int i; | ||
67 | |||
68 | at91rm9200_map_io(); | 69 | at91rm9200_map_io(); |
69 | 70 | ||
70 | /* Initialize clocks: 18.432 MHz crystal */ | 71 | /* Initialize clocks: 18.432 MHz crystal */ |
@@ -73,16 +74,8 @@ static void __init dk_map_io(void) | |||
73 | /* Setup the LEDs */ | 74 | /* Setup the LEDs */ |
74 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); | 75 | at91_init_leds(AT91_PIN_PB2, AT91_PIN_PB2); |
75 | 76 | ||
76 | #ifdef CONFIG_SERIAL_AT91 | 77 | /* Setup the serial ports and console */ |
77 | at91_console_port = DK_SERIAL_CONSOLE; | 78 | at91_init_serial(&dk_uart_config); |
78 | memcpy(at91_serial_map, serial, sizeof(serial)); | ||
79 | |||
80 | /* Register UARTs */ | ||
81 | for (i = 0; i < AT91_NR_UART; i++) { | ||
82 | if (at91_serial_map[i] >= 0) | ||
83 | at91_register_uart(i, at91_serial_map[i]); | ||
84 | } | ||
85 | #endif | ||
86 | } | 79 | } |
87 | 80 | ||
88 | static struct at91_eth_data __initdata dk_eth_data = { | 81 | static struct at91_eth_data __initdata dk_eth_data = { |
@@ -111,16 +104,48 @@ static struct at91_mmc_data __initdata dk_mmc_data = { | |||
111 | .wire4 = 1, | 104 | .wire4 = 1, |
112 | }; | 105 | }; |
113 | 106 | ||
107 | static struct spi_board_info dk_spi_devices[] = { | ||
108 | { /* DataFlash chip */ | ||
109 | .modalias = "mtd_dataflash", | ||
110 | .chip_select = 0, | ||
111 | .max_speed_hz = 15 * 1000 * 1000, | ||
112 | }, | ||
113 | { /* UR6HCPS2-SP40 PS2-to-SPI adapter */ | ||
114 | .modalias = "ur6hcps2", | ||
115 | .chip_select = 1, | ||
116 | .max_speed_hz = 250 * 1000, | ||
117 | }, | ||
118 | { /* TLV1504 ADC, 4 channels, 10 bits; one is a temp sensor */ | ||
119 | .modalias = "tlv1504", | ||
120 | .chip_select = 2, | ||
121 | .max_speed_hz = 20 * 1000 * 1000, | ||
122 | }, | ||
123 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD | ||
124 | { /* DataFlash card */ | ||
125 | .modalias = "mtd_dataflash", | ||
126 | .chip_select = 3, | ||
127 | .max_speed_hz = 15 * 1000 * 1000, | ||
128 | } | ||
129 | #endif | ||
130 | }; | ||
131 | |||
114 | static void __init dk_board_init(void) | 132 | static void __init dk_board_init(void) |
115 | { | 133 | { |
134 | /* Serial */ | ||
135 | at91_add_device_serial(); | ||
116 | /* Ethernet */ | 136 | /* Ethernet */ |
117 | at91_add_device_eth(&dk_eth_data); | 137 | at91_add_device_eth(&dk_eth_data); |
118 | /* USB Host */ | 138 | /* USB Host */ |
119 | at91_add_device_usbh(&dk_usbh_data); | 139 | at91_add_device_usbh(&dk_usbh_data); |
120 | /* USB Device */ | 140 | /* USB Device */ |
121 | at91_add_device_udc(&dk_udc_data); | 141 | at91_add_device_udc(&dk_udc_data); |
142 | at91_set_multi_drive(dk_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ | ||
122 | /* Compact Flash */ | 143 | /* Compact Flash */ |
123 | at91_add_device_cf(&dk_cf_data); | 144 | at91_add_device_cf(&dk_cf_data); |
145 | /* I2C */ | ||
146 | at91_add_device_i2c(); | ||
147 | /* SPI */ | ||
148 | at91_add_device_spi(dk_spi_devices, ARRAY_SIZE(dk_spi_devices)); | ||
124 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD | 149 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD |
125 | /* DataFlash card */ | 150 | /* DataFlash card */ |
126 | at91_set_gpio_output(AT91_PIN_PB7, 0); | 151 | at91_set_gpio_output(AT91_PIN_PB7, 0); |
diff --git a/arch/arm/mach-at91rm9200/board-eb9200.c b/arch/arm/mach-at91rm9200/board-eb9200.c new file mode 100644 index 000000000000..a3e2df968a66 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-eb9200.c | |||
@@ -0,0 +1,130 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-at91rm9200/board-eb9200.c | ||
3 | * | ||
4 | * Copyright (C) 2005 SAN People, adapted for ATEB9200 from Embest | ||
5 | * by Andrew Patrikalakis | ||
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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/device.h> | ||
28 | |||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/setup.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <asm/irq.h> | ||
33 | |||
34 | #include <asm/mach/arch.h> | ||
35 | #include <asm/mach/map.h> | ||
36 | #include <asm/mach/irq.h> | ||
37 | |||
38 | #include <asm/hardware.h> | ||
39 | #include <asm/arch/board.h> | ||
40 | #include <asm/arch/gpio.h> | ||
41 | |||
42 | #include "generic.h" | ||
43 | |||
44 | static void __init eb9200_init_irq(void) | ||
45 | { | ||
46 | /* Initialize AIC controller */ | ||
47 | at91rm9200_init_irq(NULL); | ||
48 | |||
49 | /* Set up the GPIO interrupts */ | ||
50 | at91_gpio_irq_setup(BGA_GPIO_BANKS); | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Serial port configuration. | ||
55 | * 0 .. 3 = USART0 .. USART3 | ||
56 | * 4 = DBGU | ||
57 | */ | ||
58 | static struct at91_uart_config __initdata eb9200_uart_config = { | ||
59 | .console_tty = 0, /* ttyS0 */ | ||
60 | .nr_tty = 2, | ||
61 | .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
62 | }; | ||
63 | |||
64 | static void __init eb9200_map_io(void) | ||
65 | { | ||
66 | at91rm9200_map_io(); | ||
67 | |||
68 | /* Initialize clocks: 18.432 MHz crystal */ | ||
69 | at91_clock_init(18432000); | ||
70 | |||
71 | /* Setup the serial ports and console */ | ||
72 | at91_init_serial(&eb9200_uart_config); | ||
73 | } | ||
74 | |||
75 | static struct at91_eth_data __initdata eb9200_eth_data = { | ||
76 | .phy_irq_pin = AT91_PIN_PC4, | ||
77 | .is_rmii = 1, | ||
78 | }; | ||
79 | |||
80 | static struct at91_usbh_data __initdata eb9200_usbh_data = { | ||
81 | .ports = 2, | ||
82 | }; | ||
83 | |||
84 | static struct at91_udc_data __initdata eb9200_udc_data = { | ||
85 | .vbus_pin = AT91_PIN_PD4, | ||
86 | .pullup_pin = AT91_PIN_PD5, | ||
87 | }; | ||
88 | |||
89 | static struct at91_cf_data __initdata eb9200_cf_data = { | ||
90 | .det_pin = AT91_PIN_PB0, | ||
91 | .rst_pin = AT91_PIN_PC5, | ||
92 | // .irq_pin = ... not connected | ||
93 | // .vcc_pin = ... always powered | ||
94 | }; | ||
95 | |||
96 | static struct at91_mmc_data __initdata eb9200_mmc_data = { | ||
97 | .is_b = 0, | ||
98 | .wire4 = 1, | ||
99 | }; | ||
100 | |||
101 | static void __init eb9200_board_init(void) | ||
102 | { | ||
103 | /* Serial */ | ||
104 | at91_add_device_serial(); | ||
105 | /* Ethernet */ | ||
106 | at91_add_device_eth(&eb9200_eth_data); | ||
107 | /* USB Host */ | ||
108 | at91_add_device_usbh(&eb9200_usbh_data); | ||
109 | /* USB Device */ | ||
110 | at91_add_device_udc(&eb9200_udc_data); | ||
111 | /* I2C */ | ||
112 | at91_add_device_i2c(); | ||
113 | /* Compact Flash */ | ||
114 | at91_add_device_cf(&eb9200_cf_data); | ||
115 | /* SPI */ | ||
116 | at91_add_device_spi(NULL, 0); | ||
117 | /* MMC */ | ||
118 | /* only supports 1 or 4 bit interface, not wired through to SPI */ | ||
119 | at91_add_device_mmc(&eb9200_mmc_data); | ||
120 | } | ||
121 | |||
122 | MACHINE_START(ATEB9200, "Embest ATEB9200") | ||
123 | .phys_io = AT91_BASE_SYS, | ||
124 | .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, | ||
125 | .boot_params = AT91_SDRAM_BASE + 0x100, | ||
126 | .timer = &at91rm9200_timer, | ||
127 | .map_io = eb9200_map_io, | ||
128 | .init_irq = eb9200_init_irq, | ||
129 | .init_machine = eb9200_board_init, | ||
130 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91rm9200/board-ek.c b/arch/arm/mach-at91rm9200/board-ek.c index 80d90f5135a1..72202ed830ad 100644 --- a/arch/arm/mach-at91rm9200/board-ek.c +++ b/arch/arm/mach-at91rm9200/board-ek.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/module.h> | 28 | #include <linux/module.h> |
29 | #include <linux/platform_device.h> | 29 | #include <linux/platform_device.h> |
30 | #include <linux/spi/spi.h> | ||
30 | 31 | ||
31 | #include <asm/hardware.h> | 32 | #include <asm/hardware.h> |
32 | #include <asm/setup.h> | 33 | #include <asm/setup.h> |
@@ -37,9 +38,9 @@ | |||
37 | #include <asm/mach/map.h> | 38 | #include <asm/mach/map.h> |
38 | #include <asm/mach/irq.h> | 39 | #include <asm/mach/irq.h> |
39 | 40 | ||
40 | #include <asm/arch/hardware.h> | 41 | #include <asm/hardware.h> |
41 | #include <asm/mach/serial_at91rm9200.h> | ||
42 | #include <asm/arch/board.h> | 42 | #include <asm/arch/board.h> |
43 | #include <asm/arch/gpio.h> | ||
43 | 44 | ||
44 | #include "generic.h" | 45 | #include "generic.h" |
45 | 46 | ||
@@ -57,14 +58,14 @@ static void __init ek_init_irq(void) | |||
57 | * 0 .. 3 = USART0 .. USART3 | 58 | * 0 .. 3 = USART0 .. USART3 |
58 | * 4 = DBGU | 59 | * 4 = DBGU |
59 | */ | 60 | */ |
60 | #define EK_UART_MAP { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | 61 | static struct at91_uart_config __initdata ek_uart_config = { |
61 | #define EK_SERIAL_CONSOLE 0 /* ttyS0 */ | 62 | .console_tty = 0, /* ttyS0 */ |
63 | .nr_tty = 2, | ||
64 | .tty_map = { 4, 1, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
65 | }; | ||
62 | 66 | ||
63 | static void __init ek_map_io(void) | 67 | static void __init ek_map_io(void) |
64 | { | 68 | { |
65 | int serial[AT91_NR_UART] = EK_UART_MAP; | ||
66 | int i; | ||
67 | |||
68 | at91rm9200_map_io(); | 69 | at91rm9200_map_io(); |
69 | 70 | ||
70 | /* Initialize clocks: 18.432 MHz crystal */ | 71 | /* Initialize clocks: 18.432 MHz crystal */ |
@@ -73,16 +74,8 @@ static void __init ek_map_io(void) | |||
73 | /* Setup the LEDs */ | 74 | /* Setup the LEDs */ |
74 | at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); | 75 | at91_init_leds(AT91_PIN_PB1, AT91_PIN_PB2); |
75 | 76 | ||
76 | #ifdef CONFIG_SERIAL_AT91 | 77 | /* Setup the serial ports and console */ |
77 | at91_console_port = EK_SERIAL_CONSOLE; | 78 | at91_init_serial(&ek_uart_config); |
78 | memcpy(at91_serial_map, serial, sizeof(serial)); | ||
79 | |||
80 | /* Register UARTs */ | ||
81 | for (i = 0; i < AT91_NR_UART; i++) { | ||
82 | if (serial[i] >= 0) | ||
83 | at91_register_uart(i, serial[i]); | ||
84 | } | ||
85 | #endif | ||
86 | } | 79 | } |
87 | 80 | ||
88 | static struct at91_eth_data __initdata ek_eth_data = { | 81 | static struct at91_eth_data __initdata ek_eth_data = { |
@@ -106,14 +99,36 @@ static struct at91_mmc_data __initdata ek_mmc_data = { | |||
106 | .wp_pin = AT91_PIN_PA17, | 99 | .wp_pin = AT91_PIN_PA17, |
107 | }; | 100 | }; |
108 | 101 | ||
102 | static struct spi_board_info ek_spi_devices[] = { | ||
103 | { /* DataFlash chip */ | ||
104 | .modalias = "mtd_dataflash", | ||
105 | .chip_select = 0, | ||
106 | .max_speed_hz = 15 * 1000 * 1000, | ||
107 | }, | ||
108 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD | ||
109 | { /* DataFlash card */ | ||
110 | .modalias = "mtd_dataflash", | ||
111 | .chip_select = 3, | ||
112 | .max_speed_hz = 15 * 1000 * 1000, | ||
113 | }, | ||
114 | #endif | ||
115 | }; | ||
116 | |||
109 | static void __init ek_board_init(void) | 117 | static void __init ek_board_init(void) |
110 | { | 118 | { |
119 | /* Serial */ | ||
120 | at91_add_device_serial(); | ||
111 | /* Ethernet */ | 121 | /* Ethernet */ |
112 | at91_add_device_eth(&ek_eth_data); | 122 | at91_add_device_eth(&ek_eth_data); |
113 | /* USB Host */ | 123 | /* USB Host */ |
114 | at91_add_device_usbh(&ek_usbh_data); | 124 | at91_add_device_usbh(&ek_usbh_data); |
115 | /* USB Device */ | 125 | /* USB Device */ |
116 | at91_add_device_udc(&ek_udc_data); | 126 | at91_add_device_udc(&ek_udc_data); |
127 | at91_set_multi_drive(ek_udc_data.pullup_pin, 1); /* pullup_pin is connected to reset */ | ||
128 | /* I2C */ | ||
129 | at91_add_device_i2c(); | ||
130 | /* SPI */ | ||
131 | at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); | ||
117 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD | 132 | #ifdef CONFIG_MTD_AT91_DATAFLASH_CARD |
118 | /* DataFlash card */ | 133 | /* DataFlash card */ |
119 | at91_set_gpio_output(AT91_PIN_PB22, 0); | 134 | at91_set_gpio_output(AT91_PIN_PB22, 0); |
diff --git a/arch/arm/mach-at91rm9200/board-kafa.c b/arch/arm/mach-at91rm9200/board-kafa.c new file mode 100644 index 000000000000..bf760c5e0c46 --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kafa.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-at91rm9200/board-kafa.c | ||
3 | * | ||
4 | * Copyright (C) 2006 Sperry-Sun | ||
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 as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/config.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | |||
28 | #include <asm/hardware.h> | ||
29 | #include <asm/setup.h> | ||
30 | #include <asm/mach-types.h> | ||
31 | #include <asm/irq.h> | ||
32 | |||
33 | #include <asm/mach/arch.h> | ||
34 | #include <asm/mach/map.h> | ||
35 | #include <asm/mach/irq.h> | ||
36 | |||
37 | #include <asm/hardware.h> | ||
38 | #include <asm/arch/board.h> | ||
39 | #include <asm/arch/gpio.h> | ||
40 | |||
41 | #include "generic.h" | ||
42 | |||
43 | static void __init kafa_init_irq(void) | ||
44 | { | ||
45 | /* Initialize AIC controller */ | ||
46 | at91rm9200_init_irq(NULL); | ||
47 | |||
48 | /* Set up the GPIO interrupts */ | ||
49 | at91_gpio_irq_setup(PQFP_GPIO_BANKS); | ||
50 | } | ||
51 | |||
52 | /* | ||
53 | * Serial port configuration. | ||
54 | * 0 .. 3 = USART0 .. USART3 | ||
55 | * 4 = DBGU | ||
56 | */ | ||
57 | static struct at91_uart_config __initdata kafa_uart_config = { | ||
58 | .console_tty = 0, /* ttyS0 */ | ||
59 | .nr_tty = 2, | ||
60 | .tty_map = { 4, 0, -1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
61 | }; | ||
62 | |||
63 | static void __init kafa_map_io(void) | ||
64 | { | ||
65 | at91rm9200_map_io(); | ||
66 | |||
67 | /* Initialize clocks: 18.432 MHz crystal */ | ||
68 | at91_clock_init(18432000); | ||
69 | |||
70 | /* Set up the LEDs */ | ||
71 | at91_init_leds(AT91_PIN_PB4, AT91_PIN_PB4); | ||
72 | |||
73 | /* Setup the serial ports and console */ | ||
74 | at91_init_serial(&kafa_uart_config); | ||
75 | } | ||
76 | |||
77 | static struct at91_eth_data __initdata kafa_eth_data = { | ||
78 | .phy_irq_pin = AT91_PIN_PC4, | ||
79 | .is_rmii = 0, | ||
80 | }; | ||
81 | |||
82 | static struct at91_usbh_data __initdata kafa_usbh_data = { | ||
83 | .ports = 1, | ||
84 | }; | ||
85 | |||
86 | static struct at91_udc_data __initdata kafa_udc_data = { | ||
87 | .vbus_pin = AT91_PIN_PB6, | ||
88 | .pullup_pin = AT91_PIN_PB7, | ||
89 | }; | ||
90 | |||
91 | static void __init kafa_board_init(void) | ||
92 | { | ||
93 | /* Serial */ | ||
94 | at91_add_device_serial(); | ||
95 | /* Ethernet */ | ||
96 | at91_add_device_eth(&kafa_eth_data); | ||
97 | /* USB Host */ | ||
98 | at91_add_device_usbh(&kafa_usbh_data); | ||
99 | /* USB Device */ | ||
100 | at91_add_device_udc(&kafa_udc_data); | ||
101 | /* I2C */ | ||
102 | at91_add_device_i2c(); | ||
103 | /* SPI */ | ||
104 | at91_add_device_spi(NULL, 0); | ||
105 | } | ||
106 | |||
107 | MACHINE_START(KAFA, "Sperry-Sun KAFA") | ||
108 | /* Maintainer: Sergei Sharonov */ | ||
109 | .phys_io = AT91_BASE_SYS, | ||
110 | .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, | ||
111 | .boot_params = AT91_SDRAM_BASE + 0x100, | ||
112 | .timer = &at91rm9200_timer, | ||
113 | .map_io = kafa_map_io, | ||
114 | .init_irq = kafa_init_irq, | ||
115 | .init_machine = kafa_board_init, | ||
116 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91rm9200/board-kb9202.c b/arch/arm/mach-at91rm9200/board-kb9202.c new file mode 100644 index 000000000000..f06d2b54cc9a --- /dev/null +++ b/arch/arm/mach-at91rm9200/board-kb9202.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-at91rm9200/board-kb9202.c | ||
3 | * | ||
4 | * Copyright (c) 2005 kb_admin | ||
5 | * KwikByte, 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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | */ | ||
21 | |||
22 | #include <linux/config.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/mm.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/platform_device.h> | ||
28 | |||
29 | #include <asm/hardware.h> | ||
30 | #include <asm/setup.h> | ||
31 | #include <asm/mach-types.h> | ||
32 | #include <asm/irq.h> | ||
33 | |||
34 | #include <asm/mach/arch.h> | ||
35 | #include <asm/mach/map.h> | ||
36 | #include <asm/mach/irq.h> | ||
37 | |||
38 | #include <asm/hardware.h> | ||
39 | #include <asm/arch/board.h> | ||
40 | #include <asm/arch/gpio.h> | ||
41 | |||
42 | #include "generic.h" | ||
43 | |||
44 | static void __init kb9202_init_irq(void) | ||
45 | { | ||
46 | /* Initialize AIC controller */ | ||
47 | at91rm9200_init_irq(NULL); | ||
48 | |||
49 | /* Set up the GPIO interrupts */ | ||
50 | at91_gpio_irq_setup(PQFP_GPIO_BANKS); | ||
51 | } | ||
52 | |||
53 | /* | ||
54 | * Serial port configuration. | ||
55 | * 0 .. 3 = USART0 .. USART3 | ||
56 | * 4 = DBGU | ||
57 | */ | ||
58 | static struct at91_uart_config __initdata kb9202_uart_config = { | ||
59 | .console_tty = 0, /* ttyS0 */ | ||
60 | .nr_tty = 3, | ||
61 | .tty_map = { 4, 0, 1, -1, -1 } /* ttyS0, ..., ttyS4 */ | ||
62 | }; | ||
63 | |||
64 | static void __init kb9202_map_io(void) | ||
65 | { | ||
66 | at91rm9200_map_io(); | ||
67 | |||
68 | /* Initialize clocks: 10 MHz crystal */ | ||
69 | at91_clock_init(10000000); | ||
70 | |||
71 | /* Set up the LEDs */ | ||
72 | at91_init_leds(AT91_PIN_PC19, AT91_PIN_PC18); | ||
73 | |||
74 | /* Setup the serial ports and console */ | ||
75 | at91_init_serial(&kb9202_uart_config); | ||
76 | } | ||
77 | |||
78 | static struct at91_eth_data __initdata kb9202_eth_data = { | ||
79 | .phy_irq_pin = AT91_PIN_PB29, | ||
80 | .is_rmii = 0, | ||
81 | }; | ||
82 | |||
83 | static struct at91_usbh_data __initdata kb9202_usbh_data = { | ||
84 | .ports = 1, | ||
85 | }; | ||
86 | |||
87 | static struct at91_udc_data __initdata kb9202_udc_data = { | ||
88 | .vbus_pin = AT91_PIN_PB24, | ||
89 | .pullup_pin = AT91_PIN_PB22, | ||
90 | }; | ||
91 | |||
92 | static struct at91_mmc_data __initdata kb9202_mmc_data = { | ||
93 | .det_pin = AT91_PIN_PB2, | ||
94 | .is_b = 0, | ||
95 | .wire4 = 1, | ||
96 | }; | ||
97 | |||
98 | static void __init kb9202_board_init(void) | ||
99 | { | ||
100 | /* Serial */ | ||
101 | at91_add_device_serial(); | ||
102 | /* Ethernet */ | ||
103 | at91_add_device_eth(&kb9202_eth_data); | ||
104 | /* USB Host */ | ||
105 | at91_add_device_usbh(&kb9202_usbh_data); | ||
106 | /* USB Device */ | ||
107 | at91_add_device_udc(&kb9202_udc_data); | ||
108 | /* MMC */ | ||
109 | at91_add_device_mmc(&kb9202_mmc_data); | ||
110 | /* I2C */ | ||
111 | at91_add_device_i2c(); | ||
112 | /* SPI */ | ||
113 | at91_add_device_spi(NULL, 0); | ||
114 | } | ||
115 | |||
116 | MACHINE_START(KB9200, "KB920x") | ||
117 | /* Maintainer: KwikByte, Inc. */ | ||
118 | .phys_io = AT91_BASE_SYS, | ||
119 | .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, | ||
120 | .boot_params = AT91_SDRAM_BASE + 0x100, | ||
121 | .timer = &at91rm9200_timer, | ||
122 | .map_io = kb9202_map_io, | ||
123 | .init_irq = kb9202_init_irq, | ||
124 | .init_machine = kb9202_board_init, | ||
125 | MACHINE_END | ||
diff --git a/arch/arm/mach-at91rm9200/clock.c b/arch/arm/mach-at91rm9200/clock.c index 8b95467c6d61..edc2cc837ae6 100644 --- a/arch/arm/mach-at91rm9200/clock.c +++ b/arch/arm/mach-at91rm9200/clock.c | |||
@@ -27,12 +27,10 @@ | |||
27 | #include <asm/io.h> | 27 | #include <asm/io.h> |
28 | #include <asm/mach-types.h> | 28 | #include <asm/mach-types.h> |
29 | 29 | ||
30 | #include <asm/arch/hardware.h> | 30 | #include <asm/hardware.h> |
31 | #include <asm/arch/board.h> /* for master clock global */ | ||
32 | 31 | ||
33 | #include "generic.h" | 32 | #include "generic.h" |
34 | 33 | ||
35 | #undef DEBUG | ||
36 | 34 | ||
37 | /* | 35 | /* |
38 | * There's a lot more which can be done with clocks, including cpufreq | 36 | * There's a lot more which can be done with clocks, including cpufreq |
@@ -41,7 +39,9 @@ | |||
41 | */ | 39 | */ |
42 | 40 | ||
43 | struct clk { | 41 | struct clk { |
44 | const char *name; | 42 | const char *name; /* unique clock name */ |
43 | const char *function; /* function of the clock */ | ||
44 | struct device *dev; /* device associated with function */ | ||
45 | unsigned long rate_hz; | 45 | unsigned long rate_hz; |
46 | struct clk *parent; | 46 | struct clk *parent; |
47 | u32 pmc_mask; | 47 | u32 pmc_mask; |
@@ -71,15 +71,14 @@ static struct clk clk32k = { | |||
71 | }; | 71 | }; |
72 | static struct clk main_clk = { | 72 | static struct clk main_clk = { |
73 | .name = "main", | 73 | .name = "main", |
74 | .pmc_mask = 1 << 0, /* in PMC_SR */ | 74 | .pmc_mask = AT91_PMC_MOSCS, /* in PMC_SR */ |
75 | .users = 1, | ||
76 | .id = 1, | 75 | .id = 1, |
77 | .primary = 1, | 76 | .primary = 1, |
78 | }; | 77 | }; |
79 | static struct clk plla = { | 78 | static struct clk plla = { |
80 | .name = "plla", | 79 | .name = "plla", |
81 | .parent = &main_clk, | 80 | .parent = &main_clk, |
82 | .pmc_mask = 1 << 1, /* in PMC_SR */ | 81 | .pmc_mask = AT91_PMC_LOCKA, /* in PMC_SR */ |
83 | .id = 2, | 82 | .id = 2, |
84 | .primary = 1, | 83 | .primary = 1, |
85 | .pll = 1, | 84 | .pll = 1, |
@@ -105,7 +104,7 @@ static void pllb_mode(struct clk *clk, int is_on) | |||
105 | static struct clk pllb = { | 104 | static struct clk pllb = { |
106 | .name = "pllb", | 105 | .name = "pllb", |
107 | .parent = &main_clk, | 106 | .parent = &main_clk, |
108 | .pmc_mask = 1 << 2, /* in PMC_SR */ | 107 | .pmc_mask = AT91_PMC_LOCKB, /* in PMC_SR */ |
109 | .mode = pllb_mode, | 108 | .mode = pllb_mode, |
110 | .id = 3, | 109 | .id = 3, |
111 | .primary = 1, | 110 | .primary = 1, |
@@ -177,8 +176,7 @@ static struct clk pck3 = { | |||
177 | */ | 176 | */ |
178 | static struct clk mck = { | 177 | static struct clk mck = { |
179 | .name = "mck", | 178 | .name = "mck", |
180 | .pmc_mask = 1 << 3, /* in PMC_SR */ | 179 | .pmc_mask = AT91_PMC_MCKRDY, /* in PMC_SR */ |
181 | .users = 1, /* (must be) always on */ | ||
182 | }; | 180 | }; |
183 | 181 | ||
184 | static void pmc_periph_mode(struct clk *clk, int is_on) | 182 | static void pmc_periph_mode(struct clk *clk, int is_on) |
@@ -249,6 +247,30 @@ static struct clk spi_clk = { | |||
249 | .pmc_mask = 1 << AT91_ID_SPI, | 247 | .pmc_mask = 1 << AT91_ID_SPI, |
250 | .mode = pmc_periph_mode, | 248 | .mode = pmc_periph_mode, |
251 | }; | 249 | }; |
250 | static struct clk pioA_clk = { | ||
251 | .name = "pioA_clk", | ||
252 | .parent = &mck, | ||
253 | .pmc_mask = 1 << AT91_ID_PIOA, | ||
254 | .mode = pmc_periph_mode, | ||
255 | }; | ||
256 | static struct clk pioB_clk = { | ||
257 | .name = "pioB_clk", | ||
258 | .parent = &mck, | ||
259 | .pmc_mask = 1 << AT91_ID_PIOB, | ||
260 | .mode = pmc_periph_mode, | ||
261 | }; | ||
262 | static struct clk pioC_clk = { | ||
263 | .name = "pioC_clk", | ||
264 | .parent = &mck, | ||
265 | .pmc_mask = 1 << AT91_ID_PIOC, | ||
266 | .mode = pmc_periph_mode, | ||
267 | }; | ||
268 | static struct clk pioD_clk = { | ||
269 | .name = "pioD_clk", | ||
270 | .parent = &mck, | ||
271 | .pmc_mask = 1 << AT91_ID_PIOD, | ||
272 | .mode = pmc_periph_mode, | ||
273 | }; | ||
252 | 274 | ||
253 | static struct clk *const clock_list[] = { | 275 | static struct clk *const clock_list[] = { |
254 | /* four primary clocks -- MUST BE FIRST! */ | 276 | /* four primary clocks -- MUST BE FIRST! */ |
@@ -279,21 +301,46 @@ static struct clk *const clock_list[] = { | |||
279 | &udc_clk, | 301 | &udc_clk, |
280 | &twi_clk, | 302 | &twi_clk, |
281 | &spi_clk, | 303 | &spi_clk, |
304 | &pioA_clk, | ||
305 | &pioB_clk, | ||
306 | &pioC_clk, | ||
307 | &pioD_clk, | ||
282 | // ssc0..ssc2 | 308 | // ssc0..ssc2 |
283 | // tc0..tc5 | 309 | // tc0..tc5 |
310 | // irq0..irq6 | ||
284 | &ohci_clk, | 311 | &ohci_clk, |
285 | ðer_clk, | 312 | ðer_clk, |
286 | }; | 313 | }; |
287 | 314 | ||
288 | 315 | ||
316 | /* | ||
317 | * Associate a particular clock with a function (eg, "uart") and device. | ||
318 | * The drivers can then request the same 'function' with several different | ||
319 | * devices and not care about which clock name to use. | ||
320 | */ | ||
321 | void __init at91_clock_associate(const char *id, struct device *dev, const char *func) | ||
322 | { | ||
323 | struct clk *clk = clk_get(NULL, id); | ||
324 | |||
325 | if (!dev || !clk || !IS_ERR(clk_get(dev, func))) | ||
326 | return; | ||
327 | |||
328 | clk->function = func; | ||
329 | clk->dev = dev; | ||
330 | } | ||
331 | |||
289 | /* clocks are all static for now; no refcounting necessary */ | 332 | /* clocks are all static for now; no refcounting necessary */ |
290 | struct clk *clk_get(struct device *dev, const char *id) | 333 | struct clk *clk_get(struct device *dev, const char *id) |
291 | { | 334 | { |
292 | int i; | 335 | int i; |
293 | 336 | ||
294 | for (i = 0; i < ARRAY_SIZE(clock_list); i++) { | 337 | for (i = 0; i < ARRAY_SIZE(clock_list); i++) { |
295 | if (strcmp(id, clock_list[i]->name) == 0) | 338 | struct clk *clk = clock_list[i]; |
296 | return clock_list[i]; | 339 | |
340 | if (strcmp(id, clk->name) == 0) | ||
341 | return clk; | ||
342 | if (clk->function && (dev == clk->dev) && strcmp(id, clk->function) == 0) | ||
343 | return clk; | ||
297 | } | 344 | } |
298 | 345 | ||
299 | return ERR_PTR(-ENOENT); | 346 | return ERR_PTR(-ENOENT); |
@@ -593,6 +640,30 @@ fail: | |||
593 | return 0; | 640 | return 0; |
594 | } | 641 | } |
595 | 642 | ||
643 | |||
644 | /* | ||
645 | * Several unused clocks may be active. Turn them off. | ||
646 | */ | ||
647 | static void at91_periphclk_reset(void) | ||
648 | { | ||
649 | unsigned long reg; | ||
650 | int i; | ||
651 | |||
652 | reg = at91_sys_read(AT91_PMC_PCSR); | ||
653 | |||
654 | for (i = 0; i < ARRAY_SIZE(clock_list); i++) { | ||
655 | struct clk *clk = clock_list[i]; | ||
656 | |||
657 | if (clk->mode != pmc_periph_mode) | ||
658 | continue; | ||
659 | |||
660 | if (clk->users > 0) | ||
661 | reg &= ~clk->pmc_mask; | ||
662 | } | ||
663 | |||
664 | at91_sys_write(AT91_PMC_PCDR, reg); | ||
665 | } | ||
666 | |||
596 | int __init at91_clock_init(unsigned long main_clock) | 667 | int __init at91_clock_init(unsigned long main_clock) |
597 | { | 668 | { |
598 | unsigned tmp, freq, mckr; | 669 | unsigned tmp, freq, mckr; |
@@ -626,7 +697,6 @@ int __init at91_clock_init(unsigned long main_clock) | |||
626 | */ | 697 | */ |
627 | at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; | 698 | at91_pllb_usb_init = at91_pll_calc(main_clock, 48000000 * 2) | AT91_PMC_USB96M; |
628 | pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); | 699 | pllb.rate_hz = at91_pll_rate(&pllb, main_clock, at91_pllb_usb_init); |
629 | at91_sys_write(AT91_PMC_PCDR, (1 << AT91_ID_UHP) | (1 << AT91_ID_UDP)); | ||
630 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); | 700 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_UHP | AT91_PMC_UDP); |
631 | at91_sys_write(AT91_CKGR_PLLBR, 0); | 701 | at91_sys_write(AT91_CKGR_PLLBR, 0); |
632 | at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); | 702 | at91_sys_write(AT91_PMC_SCER, AT91_PMC_MCKUDP); |
@@ -640,19 +710,18 @@ int __init at91_clock_init(unsigned long main_clock) | |||
640 | */ | 710 | */ |
641 | mckr = at91_sys_read(AT91_PMC_MCKR); | 711 | mckr = at91_sys_read(AT91_PMC_MCKR); |
642 | mck.parent = clock_list[mckr & AT91_PMC_CSS]; | 712 | mck.parent = clock_list[mckr & AT91_PMC_CSS]; |
643 | mck.parent->users++; | ||
644 | freq = mck.parent->rate_hz; | 713 | freq = mck.parent->rate_hz; |
645 | freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ | 714 | freq /= (1 << ((mckr >> 2) & 3)); /* prescale */ |
646 | mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ | 715 | mck.rate_hz = freq / (1 + ((mckr >> 8) & 3)); /* mdiv */ |
647 | 716 | ||
717 | /* MCK and CPU clock are "always on" */ | ||
718 | clk_enable(&mck); | ||
719 | |||
648 | printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", | 720 | printk("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", |
649 | freq / 1000000, (unsigned) mck.rate_hz / 1000000, | 721 | freq / 1000000, (unsigned) mck.rate_hz / 1000000, |
650 | (unsigned) main_clock / 1000000, | 722 | (unsigned) main_clock / 1000000, |
651 | ((unsigned) main_clock % 1000000) / 1000); | 723 | ((unsigned) main_clock % 1000000) / 1000); |
652 | 724 | ||
653 | /* FIXME get rid of master_clock global */ | ||
654 | at91_master_clock = mck.rate_hz; | ||
655 | |||
656 | #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS | 725 | #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS |
657 | /* establish PCK0..PCK3 parentage */ | 726 | /* establish PCK0..PCK3 parentage */ |
658 | for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) { | 727 | for (tmp = 0; tmp < ARRAY_SIZE(clock_list); tmp++) { |
@@ -663,19 +732,28 @@ int __init at91_clock_init(unsigned long main_clock) | |||
663 | continue; | 732 | continue; |
664 | 733 | ||
665 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); | 734 | pckr = at91_sys_read(AT91_PMC_PCKR(clk->id)); |
666 | parent = clock_list[pckr & 3]; | 735 | parent = clock_list[pckr & AT91_PMC_CSS]; |
667 | clk->parent = parent; | 736 | clk->parent = parent; |
668 | clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); | 737 | clk->rate_hz = parent->rate_hz / (1 << ((pckr >> 2) & 3)); |
738 | |||
739 | if (clk->users == 0) { | ||
740 | /* not being used, so switch it off */ | ||
741 | at91_sys_write(AT91_PMC_SCDR, clk->pmc_mask); | ||
742 | } | ||
669 | } | 743 | } |
670 | #else | 744 | #else |
671 | /* disable unused clocks */ | 745 | /* disable all programmable clocks */ |
672 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); | 746 | at91_sys_write(AT91_PMC_SCDR, AT91_PMC_PCK0 | AT91_PMC_PCK1 | AT91_PMC_PCK2 | AT91_PMC_PCK3); |
673 | #endif /* CONFIG_AT91_PROGRAMMABLE_CLOCKS */ | 747 | #endif |
674 | 748 | ||
675 | /* FIXME several unused clocks may still be active... provide | 749 | /* enable the PIO clocks */ |
676 | * a CONFIG option to turn off all unused clocks at some point | 750 | clk_enable(&pioA_clk); |
677 | * before driver init starts. | 751 | clk_enable(&pioB_clk); |
678 | */ | 752 | clk_enable(&pioC_clk); |
753 | clk_enable(&pioD_clk); | ||
754 | |||
755 | /* disable all other unused peripheral clocks */ | ||
756 | at91_periphclk_reset(); | ||
679 | 757 | ||
680 | return 0; | 758 | return 0; |
681 | } | 759 | } |
diff --git a/arch/arm/mach-at91rm9200/common.c b/arch/arm/mach-at91rm9200/common.c index 3848fd2d5596..e836f8537a1d 100644 --- a/arch/arm/mach-at91rm9200/common.c +++ b/arch/arm/mach-at91rm9200/common.c | |||
@@ -16,7 +16,8 @@ | |||
16 | #include <asm/mach/arch.h> | 16 | #include <asm/mach/arch.h> |
17 | #include <asm/mach/map.h> | 17 | #include <asm/mach/map.h> |
18 | 18 | ||
19 | #include <asm/arch/hardware.h> | 19 | #include <asm/hardware.h> |
20 | #include "generic.h" | ||
20 | 21 | ||
21 | static struct map_desc at91rm9200_io_desc[] __initdata = { | 22 | static struct map_desc at91rm9200_io_desc[] __initdata = { |
22 | { | 23 | { |
@@ -94,6 +95,11 @@ static struct map_desc at91rm9200_io_desc[] __initdata = { | |||
94 | .pfn = __phys_to_pfn(AT91_BASE_TCB0), | 95 | .pfn = __phys_to_pfn(AT91_BASE_TCB0), |
95 | .length = SZ_16K, | 96 | .length = SZ_16K, |
96 | .type = MT_DEVICE, | 97 | .type = MT_DEVICE, |
98 | }, { | ||
99 | .virtual = AT91_SRAM_VIRT_BASE, | ||
100 | .pfn = __phys_to_pfn(AT91_SRAM_BASE), | ||
101 | .length = AT91_SRAM_SIZE, | ||
102 | .type = MT_DEVICE, | ||
97 | }, | 103 | }, |
98 | }; | 104 | }; |
99 | 105 | ||
@@ -102,14 +108,3 @@ void __init at91rm9200_map_io(void) | |||
102 | iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); | 108 | iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); |
103 | } | 109 | } |
104 | 110 | ||
105 | |||
106 | unsigned long at91_master_clock; | ||
107 | |||
108 | EXPORT_SYMBOL(at91_master_clock); | ||
109 | |||
110 | |||
111 | int at91_serial_map[AT91_NR_UART]; | ||
112 | int at91_console_port; | ||
113 | |||
114 | EXPORT_SYMBOL(at91_serial_map); | ||
115 | EXPORT_SYMBOL(at91_console_port); | ||
diff --git a/arch/arm/mach-at91rm9200/devices.c b/arch/arm/mach-at91rm9200/devices.c index bfe47bd6e50c..1cf85d231baa 100644 --- a/arch/arm/mach-at91rm9200/devices.c +++ b/arch/arm/mach-at91rm9200/devices.c | |||
@@ -16,9 +16,15 @@ | |||
16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | 18 | ||
19 | #include <asm/hardware.h> | ||
19 | #include <asm/arch/board.h> | 20 | #include <asm/arch/board.h> |
20 | #include <asm/arch/pio.h> | 21 | #include <asm/arch/gpio.h> |
21 | 22 | ||
23 | #include "generic.h" | ||
24 | |||
25 | #define SZ_512 0x00000200 | ||
26 | #define SZ_256 0x00000100 | ||
27 | #define SZ_16 0x00000010 | ||
22 | 28 | ||
23 | /* -------------------------------------------------------------------- | 29 | /* -------------------------------------------------------------------- |
24 | * USB Host | 30 | * USB Host |
@@ -28,7 +34,7 @@ | |||
28 | static u64 ohci_dmamask = 0xffffffffUL; | 34 | static u64 ohci_dmamask = 0xffffffffUL; |
29 | static struct at91_usbh_data usbh_data; | 35 | static struct at91_usbh_data usbh_data; |
30 | 36 | ||
31 | static struct resource at91_usbh_resource[] = { | 37 | static struct resource at91_usbh_resources[] = { |
32 | [0] = { | 38 | [0] = { |
33 | .start = AT91_UHP_BASE, | 39 | .start = AT91_UHP_BASE, |
34 | .end = AT91_UHP_BASE + SZ_1M - 1, | 40 | .end = AT91_UHP_BASE + SZ_1M - 1, |
@@ -42,15 +48,15 @@ static struct resource at91_usbh_resource[] = { | |||
42 | }; | 48 | }; |
43 | 49 | ||
44 | static struct platform_device at91rm9200_usbh_device = { | 50 | static struct platform_device at91rm9200_usbh_device = { |
45 | .name = "at91rm9200-ohci", | 51 | .name = "at91_ohci", |
46 | .id = -1, | 52 | .id = -1, |
47 | .dev = { | 53 | .dev = { |
48 | .dma_mask = &ohci_dmamask, | 54 | .dma_mask = &ohci_dmamask, |
49 | .coherent_dma_mask = 0xffffffff, | 55 | .coherent_dma_mask = 0xffffffff, |
50 | .platform_data = &usbh_data, | 56 | .platform_data = &usbh_data, |
51 | }, | 57 | }, |
52 | .resource = at91_usbh_resource, | 58 | .resource = at91_usbh_resources, |
53 | .num_resources = ARRAY_SIZE(at91_usbh_resource), | 59 | .num_resources = ARRAY_SIZE(at91_usbh_resources), |
54 | }; | 60 | }; |
55 | 61 | ||
56 | void __init at91_add_device_usbh(struct at91_usbh_data *data) | 62 | void __init at91_add_device_usbh(struct at91_usbh_data *data) |
@@ -74,11 +80,16 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data) {} | |||
74 | static struct at91_udc_data udc_data; | 80 | static struct at91_udc_data udc_data; |
75 | 81 | ||
76 | static struct resource at91_udc_resources[] = { | 82 | static struct resource at91_udc_resources[] = { |
77 | { | 83 | [0] = { |
78 | .start = AT91_BASE_UDP, | 84 | .start = AT91_BASE_UDP, |
79 | .end = AT91_BASE_UDP + SZ_16K - 1, | 85 | .end = AT91_BASE_UDP + SZ_16K - 1, |
80 | .flags = IORESOURCE_MEM, | 86 | .flags = IORESOURCE_MEM, |
81 | } | 87 | }, |
88 | [1] = { | ||
89 | .start = AT91_ID_UDP, | ||
90 | .end = AT91_ID_UDP, | ||
91 | .flags = IORESOURCE_IRQ, | ||
92 | }, | ||
82 | }; | 93 | }; |
83 | 94 | ||
84 | static struct platform_device at91rm9200_udc_device = { | 95 | static struct platform_device at91rm9200_udc_device = { |
@@ -100,10 +111,8 @@ void __init at91_add_device_udc(struct at91_udc_data *data) | |||
100 | at91_set_gpio_input(data->vbus_pin, 0); | 111 | at91_set_gpio_input(data->vbus_pin, 0); |
101 | at91_set_deglitch(data->vbus_pin, 1); | 112 | at91_set_deglitch(data->vbus_pin, 1); |
102 | } | 113 | } |
103 | if (data->pullup_pin) { | 114 | if (data->pullup_pin) |
104 | at91_set_gpio_output(data->pullup_pin, 0); | 115 | at91_set_gpio_output(data->pullup_pin, 0); |
105 | at91_set_multi_drive(data->pullup_pin, 1); | ||
106 | } | ||
107 | 116 | ||
108 | udc_data = *data; | 117 | udc_data = *data; |
109 | platform_device_register(&at91rm9200_udc_device); | 118 | platform_device_register(&at91rm9200_udc_device); |
@@ -197,7 +206,7 @@ static struct at91_cf_data cf_data; | |||
197 | static struct resource at91_cf_resources[] = { | 206 | static struct resource at91_cf_resources[] = { |
198 | [0] = { | 207 | [0] = { |
199 | .start = AT91_CF_BASE, | 208 | .start = AT91_CF_BASE, |
200 | /* ties up CS4, CS5, and CS6 */ | 209 | /* ties up CS4, CS5 and CS6 */ |
201 | .end = AT91_CF_BASE + (0x30000000 - 1), | 210 | .end = AT91_CF_BASE + (0x30000000 - 1), |
202 | .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, | 211 | .flags = IORESOURCE_MEM | IORESOURCE_MEM_8AND16BIT, |
203 | }, | 212 | }, |
@@ -231,6 +240,12 @@ void __init at91_add_device_cf(struct at91_cf_data *data) | |||
231 | at91_set_gpio_output(data->vcc_pin, 0); | 240 | at91_set_gpio_output(data->vcc_pin, 0); |
232 | at91_set_gpio_output(data->rst_pin, 0); | 241 | at91_set_gpio_output(data->rst_pin, 0); |
233 | 242 | ||
243 | /* force poweron defaults for these pins ... */ | ||
244 | at91_set_A_periph(AT91_PIN_PC9, 0); /* A25/CFRNW */ | ||
245 | at91_set_A_periph(AT91_PIN_PC10, 0); /* NCS4/CFCS */ | ||
246 | at91_set_A_periph(AT91_PIN_PC11, 0); /* NCS5/CFCE1 */ | ||
247 | at91_set_A_periph(AT91_PIN_PC12, 0); /* NCS6/CFCE2 */ | ||
248 | |||
234 | cf_data = *data; | 249 | cf_data = *data; |
235 | platform_device_register(&at91rm9200_cf_device); | 250 | platform_device_register(&at91rm9200_cf_device); |
236 | } | 251 | } |
@@ -319,6 +334,7 @@ void __init at91_add_device_mmc(struct at91_mmc_data *data) | |||
319 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} | 334 | void __init at91_add_device_mmc(struct at91_mmc_data *data) {} |
320 | #endif | 335 | #endif |
321 | 336 | ||
337 | |||
322 | /* -------------------------------------------------------------------- | 338 | /* -------------------------------------------------------------------- |
323 | * NAND / SmartMedia | 339 | * NAND / SmartMedia |
324 | * -------------------------------------------------------------------- */ | 340 | * -------------------------------------------------------------------- */ |
@@ -400,22 +416,110 @@ void __init at91_add_device_i2c(void) {} | |||
400 | 416 | ||
401 | 417 | ||
402 | /* -------------------------------------------------------------------- | 418 | /* -------------------------------------------------------------------- |
419 | * SPI | ||
420 | * -------------------------------------------------------------------- */ | ||
421 | |||
422 | #if defined(CONFIG_SPI_AT91) || defined(CONFIG_SPI_AT91_MODULE) || defined(CONFIG_AT91_SPI) || defined(CONFIG_AT91_SPI_MODULE) | ||
423 | static u64 spi_dmamask = 0xffffffffUL; | ||
424 | |||
425 | static struct resource at91_spi_resources[] = { | ||
426 | [0] = { | ||
427 | .start = AT91_BASE_SPI, | ||
428 | .end = AT91_BASE_SPI + SZ_16K - 1, | ||
429 | .flags = IORESOURCE_MEM, | ||
430 | }, | ||
431 | [1] = { | ||
432 | .start = AT91_ID_SPI, | ||
433 | .end = AT91_ID_SPI, | ||
434 | .flags = IORESOURCE_IRQ, | ||
435 | }, | ||
436 | }; | ||
437 | |||
438 | static struct platform_device at91rm9200_spi_device = { | ||
439 | .name = "at91_spi", | ||
440 | .id = 0, | ||
441 | .dev = { | ||
442 | .dma_mask = &spi_dmamask, | ||
443 | .coherent_dma_mask = 0xffffffff, | ||
444 | }, | ||
445 | .resource = at91_spi_resources, | ||
446 | .num_resources = ARRAY_SIZE(at91_spi_resources), | ||
447 | }; | ||
448 | |||
449 | static const unsigned at91_spi_standard_cs[4] = { AT91_PIN_PA3, AT91_PIN_PA4, AT91_PIN_PA5, AT91_PIN_PA6 }; | ||
450 | |||
451 | void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) | ||
452 | { | ||
453 | int i; | ||
454 | unsigned long cs_pin; | ||
455 | |||
456 | at91_set_A_periph(AT91_PIN_PA0, 0); /* MISO */ | ||
457 | at91_set_A_periph(AT91_PIN_PA1, 0); /* MOSI */ | ||
458 | at91_set_A_periph(AT91_PIN_PA2, 0); /* SPCK */ | ||
459 | |||
460 | /* Enable SPI chip-selects */ | ||
461 | for (i = 0; i < nr_devices; i++) { | ||
462 | if (devices[i].controller_data) | ||
463 | cs_pin = (unsigned long) devices[i].controller_data; | ||
464 | else | ||
465 | cs_pin = at91_spi_standard_cs[devices[i].chip_select]; | ||
466 | |||
467 | #ifdef CONFIG_SPI_AT91_MANUAL_CS | ||
468 | at91_set_gpio_output(cs_pin, 1); | ||
469 | #else | ||
470 | at91_set_A_periph(cs_pin, 0); | ||
471 | #endif | ||
472 | |||
473 | /* pass chip-select pin to driver */ | ||
474 | devices[i].controller_data = (void *) cs_pin; | ||
475 | } | ||
476 | |||
477 | spi_register_board_info(devices, nr_devices); | ||
478 | at91_clock_associate("spi0_clk", &at91rm9200_spi_device.dev, "spi"); | ||
479 | platform_device_register(&at91rm9200_spi_device); | ||
480 | } | ||
481 | #else | ||
482 | void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices) {} | ||
483 | #endif | ||
484 | |||
485 | |||
486 | /* -------------------------------------------------------------------- | ||
403 | * RTC | 487 | * RTC |
404 | * -------------------------------------------------------------------- */ | 488 | * -------------------------------------------------------------------- */ |
405 | 489 | ||
406 | #if defined(CONFIG_AT91_RTC) || defined(CONFIG_AT91_RTC_MODULE) | 490 | #if defined(CONFIG_RTC_DRV_AT91) || defined(CONFIG_RTC_DRV_AT91_MODULE) |
407 | static struct platform_device at91rm9200_rtc_device = { | 491 | static struct platform_device at91rm9200_rtc_device = { |
408 | .name = "at91_rtc", | 492 | .name = "at91_rtc", |
409 | .id = -1, | 493 | .id = -1, |
410 | .num_resources = 0, | 494 | .num_resources = 0, |
411 | }; | 495 | }; |
412 | 496 | ||
413 | void __init at91_add_device_rtc(void) | 497 | static void __init at91_add_device_rtc(void) |
414 | { | 498 | { |
415 | platform_device_register(&at91rm9200_rtc_device); | 499 | platform_device_register(&at91rm9200_rtc_device); |
416 | } | 500 | } |
417 | #else | 501 | #else |
418 | void __init at91_add_device_rtc(void) {} | 502 | static void __init at91_add_device_rtc(void) {} |
503 | #endif | ||
504 | |||
505 | |||
506 | /* -------------------------------------------------------------------- | ||
507 | * Watchdog | ||
508 | * -------------------------------------------------------------------- */ | ||
509 | |||
510 | #if defined(CONFIG_AT91_WATCHDOG) || defined(CONFIG_AT91_WATCHDOG_MODULE) | ||
511 | static struct platform_device at91rm9200_wdt_device = { | ||
512 | .name = "at91_wdt", | ||
513 | .id = -1, | ||
514 | .num_resources = 0, | ||
515 | }; | ||
516 | |||
517 | static void __init at91_add_device_watchdog(void) | ||
518 | { | ||
519 | platform_device_register(&at91rm9200_wdt_device); | ||
520 | } | ||
521 | #else | ||
522 | static void __init at91_add_device_watchdog(void) {} | ||
419 | #endif | 523 | #endif |
420 | 524 | ||
421 | 525 | ||
@@ -429,13 +533,281 @@ u8 at91_leds_timer; | |||
429 | 533 | ||
430 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) | 534 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) |
431 | { | 535 | { |
432 | at91_leds_cpu = cpu_led; | 536 | at91_leds_cpu = cpu_led; |
433 | at91_leds_timer = timer_led; | 537 | at91_leds_timer = timer_led; |
434 | } | 538 | } |
435 | |||
436 | #else | 539 | #else |
437 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} | 540 | void __init at91_init_leds(u8 cpu_led, u8 timer_led) {} |
438 | #endif | 541 | #endif |
439 | 542 | ||
440 | 543 | ||
544 | /* -------------------------------------------------------------------- | ||
545 | * UART | ||
546 | * -------------------------------------------------------------------- */ | ||
547 | |||
548 | #if defined(CONFIG_SERIAL_AT91) | ||
549 | static struct resource dbgu_resources[] = { | ||
550 | [0] = { | ||
551 | .start = AT91_VA_BASE_SYS + AT91_DBGU, | ||
552 | .end = AT91_VA_BASE_SYS + AT91_DBGU + SZ_512 - 1, | ||
553 | .flags = IORESOURCE_MEM, | ||
554 | }, | ||
555 | [1] = { | ||
556 | .start = AT91_ID_SYS, | ||
557 | .end = AT91_ID_SYS, | ||
558 | .flags = IORESOURCE_IRQ, | ||
559 | }, | ||
560 | }; | ||
561 | |||
562 | static struct at91_uart_data dbgu_data = { | ||
563 | .use_dma_tx = 0, | ||
564 | .use_dma_rx = 0, /* DBGU not capable of receive DMA */ | ||
565 | }; | ||
566 | |||
567 | static struct platform_device at91rm9200_dbgu_device = { | ||
568 | .name = "at91_usart", | ||
569 | .id = 0, | ||
570 | .dev = { | ||
571 | .platform_data = &dbgu_data, | ||
572 | .coherent_dma_mask = 0xffffffff, | ||
573 | }, | ||
574 | .resource = dbgu_resources, | ||
575 | .num_resources = ARRAY_SIZE(dbgu_resources), | ||
576 | }; | ||
577 | |||
578 | static inline void configure_dbgu_pins(void) | ||
579 | { | ||
580 | at91_set_A_periph(AT91_PIN_PA30, 0); /* DRXD */ | ||
581 | at91_set_A_periph(AT91_PIN_PA31, 1); /* DTXD */ | ||
582 | } | ||
583 | |||
584 | static struct resource uart0_resources[] = { | ||
585 | [0] = { | ||
586 | .start = AT91_BASE_US0, | ||
587 | .end = AT91_BASE_US0 + SZ_16K - 1, | ||
588 | .flags = IORESOURCE_MEM, | ||
589 | }, | ||
590 | [1] = { | ||
591 | .start = AT91_ID_US0, | ||
592 | .end = AT91_ID_US0, | ||
593 | .flags = IORESOURCE_IRQ, | ||
594 | }, | ||
595 | }; | ||
596 | |||
597 | static struct at91_uart_data uart0_data = { | ||
598 | .use_dma_tx = 1, | ||
599 | .use_dma_rx = 1, | ||
600 | }; | ||
601 | |||
602 | static struct platform_device at91rm9200_uart0_device = { | ||
603 | .name = "at91_usart", | ||
604 | .id = 1, | ||
605 | .dev = { | ||
606 | .platform_data = &uart0_data, | ||
607 | .coherent_dma_mask = 0xffffffff, | ||
608 | }, | ||
609 | .resource = uart0_resources, | ||
610 | .num_resources = ARRAY_SIZE(uart0_resources), | ||
611 | }; | ||
612 | |||
613 | static inline void configure_usart0_pins(void) | ||
614 | { | ||
615 | at91_set_A_periph(AT91_PIN_PA17, 1); /* TXD0 */ | ||
616 | at91_set_A_periph(AT91_PIN_PA18, 0); /* RXD0 */ | ||
617 | at91_set_A_periph(AT91_PIN_PA20, 0); /* CTS0 */ | ||
618 | |||
619 | /* | ||
620 | * AT91RM9200 Errata #39 - RTS0 is not internally connected to PA21. | ||
621 | * We need to drive the pin manually. Default is off (RTS is active low). | ||
622 | */ | ||
623 | at91_set_gpio_output(AT91_PIN_PA21, 1); | ||
624 | } | ||
625 | |||
626 | static struct resource uart1_resources[] = { | ||
627 | [0] = { | ||
628 | .start = AT91_BASE_US1, | ||
629 | .end = AT91_BASE_US1 + SZ_16K - 1, | ||
630 | .flags = IORESOURCE_MEM, | ||
631 | }, | ||
632 | [1] = { | ||
633 | .start = AT91_ID_US1, | ||
634 | .end = AT91_ID_US1, | ||
635 | .flags = IORESOURCE_IRQ, | ||
636 | }, | ||
637 | }; | ||
638 | |||
639 | static struct at91_uart_data uart1_data = { | ||
640 | .use_dma_tx = 1, | ||
641 | .use_dma_rx = 1, | ||
642 | }; | ||
643 | |||
644 | static struct platform_device at91rm9200_uart1_device = { | ||
645 | .name = "at91_usart", | ||
646 | .id = 2, | ||
647 | .dev = { | ||
648 | .platform_data = &uart1_data, | ||
649 | .coherent_dma_mask = 0xffffffff, | ||
650 | }, | ||
651 | .resource = uart1_resources, | ||
652 | .num_resources = ARRAY_SIZE(uart1_resources), | ||
653 | }; | ||
654 | |||
655 | static inline void configure_usart1_pins(void) | ||
656 | { | ||
657 | at91_set_A_periph(AT91_PIN_PB18, 0); /* RI1 */ | ||
658 | at91_set_A_periph(AT91_PIN_PB19, 0); /* DTR1 */ | ||
659 | at91_set_A_periph(AT91_PIN_PB20, 1); /* TXD1 */ | ||
660 | at91_set_A_periph(AT91_PIN_PB21, 0); /* RXD1 */ | ||
661 | at91_set_A_periph(AT91_PIN_PB23, 0); /* DCD1 */ | ||
662 | at91_set_A_periph(AT91_PIN_PB24, 0); /* CTS1 */ | ||
663 | at91_set_A_periph(AT91_PIN_PB25, 0); /* DSR1 */ | ||
664 | at91_set_A_periph(AT91_PIN_PB26, 0); /* RTS1 */ | ||
665 | } | ||
666 | |||
667 | static struct resource uart2_resources[] = { | ||
668 | [0] = { | ||
669 | .start = AT91_BASE_US2, | ||
670 | .end = AT91_BASE_US2 + SZ_16K - 1, | ||
671 | .flags = IORESOURCE_MEM, | ||
672 | }, | ||
673 | [1] = { | ||
674 | .start = AT91_ID_US2, | ||
675 | .end = AT91_ID_US2, | ||
676 | .flags = IORESOURCE_IRQ, | ||
677 | }, | ||
678 | }; | ||
679 | |||
680 | static struct at91_uart_data uart2_data = { | ||
681 | .use_dma_tx = 1, | ||
682 | .use_dma_rx = 1, | ||
683 | }; | ||
684 | |||
685 | static struct platform_device at91rm9200_uart2_device = { | ||
686 | .name = "at91_usart", | ||
687 | .id = 3, | ||
688 | .dev = { | ||
689 | .platform_data = &uart2_data, | ||
690 | .coherent_dma_mask = 0xffffffff, | ||
691 | }, | ||
692 | .resource = uart2_resources, | ||
693 | .num_resources = ARRAY_SIZE(uart2_resources), | ||
694 | }; | ||
695 | |||
696 | static inline void configure_usart2_pins(void) | ||
697 | { | ||
698 | at91_set_A_periph(AT91_PIN_PA22, 0); /* RXD2 */ | ||
699 | at91_set_A_periph(AT91_PIN_PA23, 1); /* TXD2 */ | ||
700 | } | ||
701 | |||
702 | static struct resource uart3_resources[] = { | ||
703 | [0] = { | ||
704 | .start = AT91_BASE_US3, | ||
705 | .end = AT91_BASE_US3 + SZ_16K - 1, | ||
706 | .flags = IORESOURCE_MEM, | ||
707 | }, | ||
708 | [1] = { | ||
709 | .start = AT91_ID_US3, | ||
710 | .end = AT91_ID_US3, | ||
711 | .flags = IORESOURCE_IRQ, | ||
712 | }, | ||
713 | }; | ||
714 | |||
715 | static struct at91_uart_data uart3_data = { | ||
716 | .use_dma_tx = 1, | ||
717 | .use_dma_rx = 1, | ||
718 | }; | ||
719 | |||
720 | static struct platform_device at91rm9200_uart3_device = { | ||
721 | .name = "at91_usart", | ||
722 | .id = 4, | ||
723 | .dev = { | ||
724 | .platform_data = &uart3_data, | ||
725 | .coherent_dma_mask = 0xffffffff, | ||
726 | }, | ||
727 | .resource = uart3_resources, | ||
728 | .num_resources = ARRAY_SIZE(uart3_resources), | ||
729 | }; | ||
730 | |||
731 | static inline void configure_usart3_pins(void) | ||
732 | { | ||
733 | at91_set_B_periph(AT91_PIN_PA5, 1); /* TXD3 */ | ||
734 | at91_set_B_periph(AT91_PIN_PA6, 0); /* RXD3 */ | ||
735 | } | ||
736 | |||
737 | struct platform_device *at91_uarts[AT91_NR_UART]; /* the UARTs to use */ | ||
738 | struct platform_device *at91_default_console_device; /* the serial console device */ | ||
739 | |||
740 | void __init at91_init_serial(struct at91_uart_config *config) | ||
741 | { | ||
742 | int i; | ||
743 | |||
744 | /* Fill in list of supported UARTs */ | ||
745 | for (i = 0; i < config->nr_tty; i++) { | ||
746 | switch (config->tty_map[i]) { | ||
747 | case 0: | ||
748 | configure_usart0_pins(); | ||
749 | at91_uarts[i] = &at91rm9200_uart0_device; | ||
750 | at91_clock_associate("usart0_clk", &at91rm9200_uart0_device.dev, "usart"); | ||
751 | break; | ||
752 | case 1: | ||
753 | configure_usart1_pins(); | ||
754 | at91_uarts[i] = &at91rm9200_uart1_device; | ||
755 | at91_clock_associate("usart1_clk", &at91rm9200_uart1_device.dev, "usart"); | ||
756 | break; | ||
757 | case 2: | ||
758 | configure_usart2_pins(); | ||
759 | at91_uarts[i] = &at91rm9200_uart2_device; | ||
760 | at91_clock_associate("usart2_clk", &at91rm9200_uart2_device.dev, "usart"); | ||
761 | break; | ||
762 | case 3: | ||
763 | configure_usart3_pins(); | ||
764 | at91_uarts[i] = &at91rm9200_uart3_device; | ||
765 | at91_clock_associate("usart3_clk", &at91rm9200_uart3_device.dev, "usart"); | ||
766 | break; | ||
767 | case 4: | ||
768 | configure_dbgu_pins(); | ||
769 | at91_uarts[i] = &at91rm9200_dbgu_device; | ||
770 | at91_clock_associate("mck", &at91rm9200_dbgu_device.dev, "usart"); | ||
771 | break; | ||
772 | default: | ||
773 | continue; | ||
774 | } | ||
775 | at91_uarts[i]->id = i; /* update ID number to mapped ID */ | ||
776 | } | ||
777 | |||
778 | /* Set serial console device */ | ||
779 | if (config->console_tty < AT91_NR_UART) | ||
780 | at91_default_console_device = at91_uarts[config->console_tty]; | ||
781 | if (!at91_default_console_device) | ||
782 | printk(KERN_INFO "AT91: No default serial console defined.\n"); | ||
783 | } | ||
784 | |||
785 | void __init at91_add_device_serial(void) | ||
786 | { | ||
787 | int i; | ||
788 | |||
789 | for (i = 0; i < AT91_NR_UART; i++) { | ||
790 | if (at91_uarts[i]) | ||
791 | platform_device_register(at91_uarts[i]); | ||
792 | } | ||
793 | } | ||
794 | #else | ||
795 | void __init at91_init_serial(struct at91_uart_config *config) {} | ||
796 | void __init at91_add_device_serial(void) {} | ||
797 | #endif | ||
798 | |||
799 | |||
441 | /* -------------------------------------------------------------------- */ | 800 | /* -------------------------------------------------------------------- */ |
801 | |||
802 | /* | ||
803 | * These devices are always present and don't need any board-specific | ||
804 | * setup. | ||
805 | */ | ||
806 | static int __init at91_add_standard_devices(void) | ||
807 | { | ||
808 | at91_add_device_rtc(); | ||
809 | at91_add_device_watchdog(); | ||
810 | return 0; | ||
811 | } | ||
812 | |||
813 | arch_initcall(at91_add_standard_devices); | ||
diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index 9bd541eba0a0..f0d969d7d874 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h | |||
@@ -16,3 +16,10 @@ extern struct sys_timer at91rm9200_timer; | |||
16 | extern void __init at91rm9200_map_io(void); | 16 | extern void __init at91rm9200_map_io(void); |
17 | 17 | ||
18 | extern int __init at91_clock_init(unsigned long main_clock); | 18 | extern int __init at91_clock_init(unsigned long main_clock); |
19 | struct device; | ||
20 | extern void __init at91_clock_associate(const char *id, struct device *dev, const char *func); | ||
21 | |||
22 | /* Power Management */ | ||
23 | extern void at91_irq_suspend(void); | ||
24 | extern void at91_irq_resume(void); | ||
25 | |||
diff --git a/arch/arm/mach-at91rm9200/gpio.c b/arch/arm/mach-at91rm9200/gpio.c index 5ab46274e1a3..83c34747087b 100644 --- a/arch/arm/mach-at91rm9200/gpio.c +++ b/arch/arm/mach-at91rm9200/gpio.c | |||
@@ -16,7 +16,7 @@ | |||
16 | 16 | ||
17 | #include <asm/io.h> | 17 | #include <asm/io.h> |
18 | #include <asm/mach/irq.h> | 18 | #include <asm/mach/irq.h> |
19 | #include <asm/arch/hardware.h> | 19 | #include <asm/hardware.h> |
20 | #include <asm/arch/gpio.h> | 20 | #include <asm/arch/gpio.h> |
21 | 21 | ||
22 | static const u32 pio_controller_offset[4] = { | 22 | static const u32 pio_controller_offset[4] = { |
@@ -213,6 +213,84 @@ EXPORT_SYMBOL(at91_get_gpio_value); | |||
213 | 213 | ||
214 | /*--------------------------------------------------------------------------*/ | 214 | /*--------------------------------------------------------------------------*/ |
215 | 215 | ||
216 | #ifdef CONFIG_PM | ||
217 | |||
218 | static u32 wakeups[BGA_GPIO_BANKS]; | ||
219 | static u32 backups[BGA_GPIO_BANKS]; | ||
220 | |||
221 | static int gpio_irq_set_wake(unsigned pin, unsigned state) | ||
222 | { | ||
223 | unsigned mask = pin_to_mask(pin); | ||
224 | |||
225 | pin -= PIN_BASE; | ||
226 | pin /= 32; | ||
227 | |||
228 | if (unlikely(pin >= BGA_GPIO_BANKS)) | ||
229 | return -EINVAL; | ||
230 | |||
231 | if (state) | ||
232 | wakeups[pin] |= mask; | ||
233 | else | ||
234 | wakeups[pin] &= ~mask; | ||
235 | |||
236 | return 0; | ||
237 | } | ||
238 | |||
239 | void at91_gpio_suspend(void) | ||
240 | { | ||
241 | int i; | ||
242 | |||
243 | for (i = 0; i < BGA_GPIO_BANKS; i++) { | ||
244 | u32 pio = pio_controller_offset[i]; | ||
245 | |||
246 | /* | ||
247 | * Note: drivers should have disabled GPIO interrupts that | ||
248 | * aren't supposed to be wakeup sources. | ||
249 | * But that is not much good on ARM..... disable_irq() does | ||
250 | * not update the hardware immediately, so the hardware mask | ||
251 | * (IMR) has the wrong value (not current, too much is | ||
252 | * permitted). | ||
253 | * | ||
254 | * Our workaround is to disable all non-wakeup IRQs ... | ||
255 | * which is exactly what correct drivers asked for in the | ||
256 | * first place! | ||
257 | */ | ||
258 | backups[i] = at91_sys_read(pio + PIO_IMR); | ||
259 | at91_sys_write(pio_controller_offset[i] + PIO_IDR, backups[i]); | ||
260 | at91_sys_write(pio_controller_offset[i] + PIO_IER, wakeups[i]); | ||
261 | |||
262 | if (!wakeups[i]) { | ||
263 | disable_irq_wake(AT91_ID_PIOA + i); | ||
264 | at91_sys_write(AT91_PMC_PCDR, 1 << (AT91_ID_PIOA + i)); | ||
265 | } else { | ||
266 | enable_irq_wake(AT91_ID_PIOA + i); | ||
267 | #ifdef CONFIG_PM_DEBUG | ||
268 | printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", "ABCD"[i], wakeups[i]); | ||
269 | #endif | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | |||
274 | void at91_gpio_resume(void) | ||
275 | { | ||
276 | int i; | ||
277 | |||
278 | for (i = 0; i < BGA_GPIO_BANKS; i++) { | ||
279 | at91_sys_write(pio_controller_offset[i] + PIO_IDR, wakeups[i]); | ||
280 | at91_sys_write(pio_controller_offset[i] + PIO_IER, backups[i]); | ||
281 | } | ||
282 | |||
283 | at91_sys_write(AT91_PMC_PCER, | ||
284 | (1 << AT91_ID_PIOA) | ||
285 | | (1 << AT91_ID_PIOB) | ||
286 | | (1 << AT91_ID_PIOC) | ||
287 | | (1 << AT91_ID_PIOD)); | ||
288 | } | ||
289 | |||
290 | #else | ||
291 | #define gpio_irq_set_wake NULL | ||
292 | #endif | ||
293 | |||
216 | 294 | ||
217 | /* Several AIC controller irqs are dispatched through this GPIO handler. | 295 | /* Several AIC controller irqs are dispatched through this GPIO handler. |
218 | * To use any AT91_PIN_* as an externally triggered IRQ, first call | 296 | * To use any AT91_PIN_* as an externally triggered IRQ, first call |
@@ -252,6 +330,7 @@ static struct irqchip gpio_irqchip = { | |||
252 | .mask = gpio_irq_mask, | 330 | .mask = gpio_irq_mask, |
253 | .unmask = gpio_irq_unmask, | 331 | .unmask = gpio_irq_unmask, |
254 | .set_type = gpio_irq_type, | 332 | .set_type = gpio_irq_type, |
333 | .set_wake = gpio_irq_set_wake, | ||
255 | }; | 334 | }; |
256 | 335 | ||
257 | static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) | 336 | static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs *regs) |
@@ -266,6 +345,7 @@ static void gpio_irq_handler(unsigned irq, struct irqdesc *desc, struct pt_regs | |||
266 | /* temporarily mask (level sensitive) parent IRQ */ | 345 | /* temporarily mask (level sensitive) parent IRQ */ |
267 | desc->chip->ack(irq); | 346 | desc->chip->ack(irq); |
268 | for (;;) { | 347 | for (;;) { |
348 | /* reading ISR acks the pending (edge triggered) GPIO interrupt */ | ||
269 | isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); | 349 | isr = __raw_readl(pio + PIO_ISR) & __raw_readl(pio + PIO_IMR); |
270 | if (!isr) | 350 | if (!isr) |
271 | break; | 351 | break; |
@@ -315,15 +395,16 @@ void __init at91_gpio_irq_setup(unsigned banks) | |||
315 | set_irq_chipdata(id, controller); | 395 | set_irq_chipdata(id, controller); |
316 | 396 | ||
317 | for (i = 0; i < 32; i++, pin++) { | 397 | for (i = 0; i < 32; i++, pin++) { |
398 | /* | ||
399 | * Can use the "simple" and not "edge" handler since it's | ||
400 | * shorter, and the AIC handles interupts sanely. | ||
401 | */ | ||
318 | set_irq_chip(pin, &gpio_irqchip); | 402 | set_irq_chip(pin, &gpio_irqchip); |
319 | set_irq_handler(pin, do_simple_IRQ); | 403 | set_irq_handler(pin, do_simple_IRQ); |
320 | set_irq_flags(pin, IRQF_VALID); | 404 | set_irq_flags(pin, IRQF_VALID); |
321 | } | 405 | } |
322 | 406 | ||
323 | set_irq_chained_handler(id, gpio_irq_handler); | 407 | set_irq_chained_handler(id, gpio_irq_handler); |
324 | |||
325 | /* enable the PIO peripheral clock */ | ||
326 | at91_sys_write(AT91_PMC_PCER, 1 << id); | ||
327 | } | 408 | } |
328 | pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); | 409 | pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, banks); |
329 | } | 410 | } |
diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index cb62bc83a1dd..70f4d7ac1533 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c | |||
@@ -92,10 +92,6 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type) | |||
92 | { | 92 | { |
93 | unsigned int smr, srctype; | 93 | unsigned int smr, srctype; |
94 | 94 | ||
95 | /* change triggering only for FIQ and external IRQ0..IRQ6 */ | ||
96 | if ((irq < AT91_ID_IRQ0) && (irq != AT91_ID_FIQ)) | ||
97 | return -EINVAL; | ||
98 | |||
99 | switch (type) { | 95 | switch (type) { |
100 | case IRQT_HIGH: | 96 | case IRQT_HIGH: |
101 | srctype = AT91_AIC_SRCTYPE_HIGH; | 97 | srctype = AT91_AIC_SRCTYPE_HIGH; |
@@ -104,9 +100,13 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type) | |||
104 | srctype = AT91_AIC_SRCTYPE_RISING; | 100 | srctype = AT91_AIC_SRCTYPE_RISING; |
105 | break; | 101 | break; |
106 | case IRQT_LOW: | 102 | case IRQT_LOW: |
103 | if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0)) /* only supported on external interrupts */ | ||
104 | return -EINVAL; | ||
107 | srctype = AT91_AIC_SRCTYPE_LOW; | 105 | srctype = AT91_AIC_SRCTYPE_LOW; |
108 | break; | 106 | break; |
109 | case IRQT_FALLING: | 107 | case IRQT_FALLING: |
108 | if ((irq > AT91_ID_FIQ) && (irq < AT91_ID_IRQ0)) /* only supported on external interrupts */ | ||
109 | return -EINVAL; | ||
110 | srctype = AT91_AIC_SRCTYPE_FALLING; | 110 | srctype = AT91_AIC_SRCTYPE_FALLING; |
111 | break; | 111 | break; |
112 | default: | 112 | default: |
@@ -118,11 +118,47 @@ static int at91rm9200_irq_type(unsigned irq, unsigned type) | |||
118 | return 0; | 118 | return 0; |
119 | } | 119 | } |
120 | 120 | ||
121 | #ifdef CONFIG_PM | ||
122 | |||
123 | static u32 wakeups; | ||
124 | static u32 backups; | ||
125 | |||
126 | static int at91rm9200_irq_set_wake(unsigned irq, unsigned value) | ||
127 | { | ||
128 | if (unlikely(irq >= 32)) | ||
129 | return -EINVAL; | ||
130 | |||
131 | if (value) | ||
132 | wakeups |= (1 << irq); | ||
133 | else | ||
134 | wakeups &= ~(1 << irq); | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | void at91_irq_suspend(void) | ||
140 | { | ||
141 | backups = at91_sys_read(AT91_AIC_IMR); | ||
142 | at91_sys_write(AT91_AIC_IDCR, backups); | ||
143 | at91_sys_write(AT91_AIC_IECR, wakeups); | ||
144 | } | ||
145 | |||
146 | void at91_irq_resume(void) | ||
147 | { | ||
148 | at91_sys_write(AT91_AIC_IDCR, wakeups); | ||
149 | at91_sys_write(AT91_AIC_IECR, backups); | ||
150 | } | ||
151 | |||
152 | #else | ||
153 | #define at91rm9200_irq_set_wake NULL | ||
154 | #endif | ||
155 | |||
121 | static struct irqchip at91rm9200_irq_chip = { | 156 | static struct irqchip at91rm9200_irq_chip = { |
122 | .ack = at91rm9200_mask_irq, | 157 | .ack = at91rm9200_mask_irq, |
123 | .mask = at91rm9200_mask_irq, | 158 | .mask = at91rm9200_mask_irq, |
124 | .unmask = at91rm9200_unmask_irq, | 159 | .unmask = at91rm9200_unmask_irq, |
125 | .set_type = at91rm9200_irq_type, | 160 | .set_type = at91rm9200_irq_type, |
161 | .set_wake = at91rm9200_irq_set_wake, | ||
126 | }; | 162 | }; |
127 | 163 | ||
128 | /* | 164 | /* |
diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c new file mode 100644 index 000000000000..47e5480feb7e --- /dev/null +++ b/arch/arm/mach-at91rm9200/pm.c | |||
@@ -0,0 +1,225 @@ | |||
1 | /* | ||
2 | * arch/arm/mach-at91rm9200/pm.c | ||
3 | * AT91 Power Management | ||
4 | * | ||
5 | * Copyright (C) 2005 David Brownell | ||
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 as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/pm.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/proc_fs.h> | ||
16 | #include <linux/pm.h> | ||
17 | #include <linux/interrupt.h> | ||
18 | #include <linux/sysfs.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | |||
22 | #include <asm/io.h> | ||
23 | #include <asm/irq.h> | ||
24 | #include <asm/atomic.h> | ||
25 | #include <asm/mach/time.h> | ||
26 | #include <asm/mach/irq.h> | ||
27 | #include <asm/mach-types.h> | ||
28 | |||
29 | #include <asm/arch/gpio.h> | ||
30 | |||
31 | #include "generic.h" | ||
32 | |||
33 | |||
34 | static int at91_pm_valid_state(suspend_state_t state) | ||
35 | { | ||
36 | switch (state) { | ||
37 | case PM_SUSPEND_ON: | ||
38 | case PM_SUSPEND_STANDBY: | ||
39 | case PM_SUSPEND_MEM: | ||
40 | return 1; | ||
41 | |||
42 | default: | ||
43 | return 0; | ||
44 | } | ||
45 | } | ||
46 | |||
47 | |||
48 | static suspend_state_t target_state; | ||
49 | |||
50 | /* | ||
51 | * Called after processes are frozen, but before we shutdown devices. | ||
52 | */ | ||
53 | static int at91_pm_prepare(suspend_state_t state) | ||
54 | { | ||
55 | target_state = state; | ||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | /* | ||
60 | * Verify that all the clocks are correct before entering | ||
61 | * slow-clock mode. | ||
62 | */ | ||
63 | static int at91_pm_verify_clocks(void) | ||
64 | { | ||
65 | unsigned long scsr; | ||
66 | int i; | ||
67 | |||
68 | scsr = at91_sys_read(AT91_PMC_SCSR); | ||
69 | |||
70 | /* USB must not be using PLLB */ | ||
71 | if ((scsr & (AT91_PMC_UHP | AT91_PMC_UDP)) != 0) { | ||
72 | pr_debug("AT91: PM - Suspend-to-RAM with USB still active\n"); | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | #ifdef CONFIG_AT91_PROGRAMMABLE_CLOCKS | ||
77 | /* PCK0..PCK3 must be disabled, or configured to use clk32k */ | ||
78 | for (i = 0; i < 4; i++) { | ||
79 | u32 css; | ||
80 | |||
81 | if ((scsr & (AT91_PMC_PCK0 << i)) == 0) | ||
82 | continue; | ||
83 | |||
84 | css = at91_sys_read(AT91_PMC_PCKR(i)) & AT91_PMC_CSS; | ||
85 | if (css != AT91_PMC_CSS_SLOW) { | ||
86 | pr_debug("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css); | ||
87 | return 0; | ||
88 | } | ||
89 | } | ||
90 | #endif | ||
91 | |||
92 | return 1; | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * Call this from platform driver suspend() to see how deeply to suspend. | ||
97 | * For example, some controllers (like OHCI) need one of the PLL clocks | ||
98 | * in order to act as a wakeup source, and those are not available when | ||
99 | * going into slow clock mode. | ||
100 | * | ||
101 | * REVISIT: generalize as clk_will_be_available(clk)? Other platforms have | ||
102 | * the very same problem (but not using at91 main_clk), and it'd be better | ||
103 | * to add one generic API rather than lots of platform-specific ones. | ||
104 | */ | ||
105 | int at91_suspend_entering_slow_clock(void) | ||
106 | { | ||
107 | return (target_state == PM_SUSPEND_MEM); | ||
108 | } | ||
109 | EXPORT_SYMBOL(at91_suspend_entering_slow_clock); | ||
110 | |||
111 | |||
112 | static void (*slow_clock)(void); | ||
113 | |||
114 | |||
115 | |||
116 | static int at91_pm_enter(suspend_state_t state) | ||
117 | { | ||
118 | at91_gpio_suspend(); | ||
119 | at91_irq_suspend(); | ||
120 | |||
121 | pr_debug("AT91: PM - wake mask %08x, pm state %d\n", | ||
122 | /* remember all the always-wake irqs */ | ||
123 | (at91_sys_read(AT91_PMC_PCSR) | ||
124 | | (1 << AT91_ID_FIQ) | ||
125 | | (1 << AT91_ID_SYS) | ||
126 | | (1 << AT91_ID_IRQ0) | ||
127 | | (1 << AT91_ID_IRQ1) | ||
128 | | (1 << AT91_ID_IRQ2) | ||
129 | | (1 << AT91_ID_IRQ3) | ||
130 | | (1 << AT91_ID_IRQ4) | ||
131 | | (1 << AT91_ID_IRQ5) | ||
132 | | (1 << AT91_ID_IRQ6)) | ||
133 | & at91_sys_read(AT91_AIC_IMR), | ||
134 | state); | ||
135 | |||
136 | switch (state) { | ||
137 | /* | ||
138 | * Suspend-to-RAM is like STANDBY plus slow clock mode, so | ||
139 | * drivers must suspend more deeply: only the master clock | ||
140 | * controller may be using the main oscillator. | ||
141 | */ | ||
142 | case PM_SUSPEND_MEM: | ||
143 | /* | ||
144 | * Ensure that clocks are in a valid state. | ||
145 | */ | ||
146 | if (!at91_pm_verify_clocks()) | ||
147 | goto error; | ||
148 | |||
149 | /* | ||
150 | * Enter slow clock mode by switching over to clk32k and | ||
151 | * turning off the main oscillator; reverse on wakeup. | ||
152 | */ | ||
153 | if (slow_clock) { | ||
154 | slow_clock(); | ||
155 | break; | ||
156 | } else { | ||
157 | /* DEVELOPMENT ONLY */ | ||
158 | pr_info("AT91: PM - no slow clock mode yet ...\n"); | ||
159 | /* FALLTHROUGH leaving master clock alone */ | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * STANDBY mode has *all* drivers suspended; ignores irqs not | ||
164 | * marked as 'wakeup' event sources; and reduces DRAM power. | ||
165 | * But otherwise it's identical to PM_SUSPEND_ON: cpu idle, and | ||
166 | * nothing fancy done with main or cpu clocks. | ||
167 | */ | ||
168 | case PM_SUSPEND_STANDBY: | ||
169 | /* | ||
170 | * NOTE: the Wait-for-Interrupt instruction needs to be | ||
171 | * in icache so the SDRAM stays in self-refresh mode until | ||
172 | * the wakeup IRQ occurs. | ||
173 | */ | ||
174 | asm("b 1f; .align 5; 1:"); | ||
175 | asm("mcr p15, 0, r0, c7, c10, 4"); /* drain write buffer */ | ||
176 | at91_sys_write(AT91_SDRAMC_SRR, 1); /* self-refresh mode */ | ||
177 | /* fall though to next state */ | ||
178 | |||
179 | case PM_SUSPEND_ON: | ||
180 | asm("mcr p15, 0, r0, c7, c0, 4"); /* wait for interrupt */ | ||
181 | break; | ||
182 | |||
183 | default: | ||
184 | pr_debug("AT91: PM - bogus suspend state %d\n", state); | ||
185 | goto error; | ||
186 | } | ||
187 | |||
188 | pr_debug("AT91: PM - wakeup %08x\n", | ||
189 | at91_sys_read(AT91_AIC_IPR) & at91_sys_read(AT91_AIC_IMR)); | ||
190 | |||
191 | error: | ||
192 | target_state = PM_SUSPEND_ON; | ||
193 | at91_irq_resume(); | ||
194 | at91_gpio_resume(); | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | |||
199 | static struct pm_ops at91_pm_ops ={ | ||
200 | .pm_disk_mode = 0, | ||
201 | .valid = at91_pm_valid_state, | ||
202 | .prepare = at91_pm_prepare, | ||
203 | .enter = at91_pm_enter, | ||
204 | }; | ||
205 | |||
206 | static int __init at91_pm_init(void) | ||
207 | { | ||
208 | printk("AT91: Power Management\n"); | ||
209 | |||
210 | #ifdef CONFIG_AT91_PM_SLOW_CLOCK | ||
211 | /* REVISIT allocations of SRAM should be dynamically managed. | ||
212 | * FIQ handlers and other components will want SRAM/TCM too... | ||
213 | */ | ||
214 | slow_clock = (void *) (AT91_VA_BASE_SRAM + (3 * SZ_4K)); | ||
215 | memcpy(slow_clock, at91rm9200_slow_clock, at91rm9200_slow_clock_sz); | ||
216 | #endif | ||
217 | |||
218 | /* Disable SDRAM low-power mode. Cannot be used with self-refresh. */ | ||
219 | at91_sys_write(AT91_SDRAMC_LPR, 0); | ||
220 | |||
221 | pm_set_ops(&at91_pm_ops); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | arch_initcall(at91_pm_init); | ||
diff --git a/arch/arm/mach-at91rm9200/time.c b/arch/arm/mach-at91rm9200/time.c index 7ffcf443b99f..fc2d7d5e4637 100644 --- a/arch/arm/mach-at91rm9200/time.c +++ b/arch/arm/mach-at91rm9200/time.c | |||
@@ -31,6 +31,8 @@ | |||
31 | #include <asm/irq.h> | 31 | #include <asm/irq.h> |
32 | #include <asm/mach/time.h> | 32 | #include <asm/mach/time.h> |
33 | 33 | ||
34 | static unsigned long last_crtr; | ||
35 | |||
34 | /* | 36 | /* |
35 | * The ST_CRTR is updated asynchronously to the master clock. It is therefore | 37 | * The ST_CRTR is updated asynchronously to the master clock. It is therefore |
36 | * necessary to read it twice (with the same value) to ensure accuracy. | 38 | * necessary to read it twice (with the same value) to ensure accuracy. |
@@ -56,7 +58,7 @@ static unsigned long at91rm9200_gettimeoffset(void) | |||
56 | { | 58 | { |
57 | unsigned long elapsed; | 59 | unsigned long elapsed; |
58 | 60 | ||
59 | elapsed = (read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV; | 61 | elapsed = (read_CRTR() - last_crtr) & AT91_ST_ALMV; |
60 | 62 | ||
61 | return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; | 63 | return (unsigned long)(elapsed * (tick_nsec / 1000)) / LATCH; |
62 | } | 64 | } |
@@ -66,15 +68,12 @@ static unsigned long at91rm9200_gettimeoffset(void) | |||
66 | */ | 68 | */ |
67 | static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 69 | static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) |
68 | { | 70 | { |
69 | unsigned long rtar; | ||
70 | |||
71 | if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ | 71 | if (at91_sys_read(AT91_ST_SR) & AT91_ST_PITS) { /* This is a shared interrupt */ |
72 | write_seqlock(&xtime_lock); | 72 | write_seqlock(&xtime_lock); |
73 | 73 | ||
74 | while (((read_CRTR() - at91_sys_read(AT91_ST_RTAR)) & AT91_ST_ALMV) >= LATCH) { | 74 | while (((read_CRTR() - last_crtr) & AT91_ST_ALMV) >= LATCH) { |
75 | timer_tick(regs); | 75 | timer_tick(regs); |
76 | rtar = (at91_sys_read(AT91_ST_RTAR) + LATCH) & AT91_ST_ALMV; | 76 | last_crtr = (last_crtr + LATCH) & AT91_ST_ALMV; |
77 | at91_sys_write(AT91_ST_RTAR, rtar); | ||
78 | } | 77 | } |
79 | 78 | ||
80 | write_sequnlock(&xtime_lock); | 79 | write_sequnlock(&xtime_lock); |
@@ -87,10 +86,24 @@ static irqreturn_t at91rm9200_timer_interrupt(int irq, void *dev_id, struct pt_r | |||
87 | 86 | ||
88 | static struct irqaction at91rm9200_timer_irq = { | 87 | static struct irqaction at91rm9200_timer_irq = { |
89 | .name = "at91_tick", | 88 | .name = "at91_tick", |
90 | .flags = SA_SHIRQ | SA_INTERRUPT, | 89 | .flags = SA_SHIRQ | SA_INTERRUPT | SA_TIMER, |
91 | .handler = at91rm9200_timer_interrupt | 90 | .handler = at91rm9200_timer_interrupt |
92 | }; | 91 | }; |
93 | 92 | ||
93 | void at91rm9200_timer_reset(void) | ||
94 | { | ||
95 | last_crtr = 0; | ||
96 | |||
97 | /* Real time counter incremented every 30.51758 microseconds */ | ||
98 | at91_sys_write(AT91_ST_RTMR, 1); | ||
99 | |||
100 | /* Set Period Interval timer */ | ||
101 | at91_sys_write(AT91_ST_PIMR, LATCH); | ||
102 | |||
103 | /* Enable Period Interval Timer interrupt */ | ||
104 | at91_sys_write(AT91_ST_IER, AT91_ST_PITS); | ||
105 | } | ||
106 | |||
94 | /* | 107 | /* |
95 | * Set up timer interrupt. | 108 | * Set up timer interrupt. |
96 | */ | 109 | */ |
@@ -100,28 +113,30 @@ void __init at91rm9200_timer_init(void) | |||
100 | at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); | 113 | at91_sys_write(AT91_ST_IDR, AT91_ST_PITS | AT91_ST_WDOVF | AT91_ST_RTTINC | AT91_ST_ALMS); |
101 | (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ | 114 | (void) at91_sys_read(AT91_ST_SR); /* Clear any pending interrupts */ |
102 | 115 | ||
103 | /* | 116 | /* Make IRQs happen for the system timer */ |
104 | * Make IRQs happen for the system timer. | ||
105 | */ | ||
106 | setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); | 117 | setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq); |
107 | 118 | ||
108 | /* Set initial alarm to 0 */ | ||
109 | at91_sys_write(AT91_ST_RTAR, 0); | ||
110 | |||
111 | /* Real time counter incremented every 30.51758 microseconds */ | ||
112 | at91_sys_write(AT91_ST_RTMR, 1); | ||
113 | |||
114 | /* Set Period Interval timer */ | ||
115 | at91_sys_write(AT91_ST_PIMR, LATCH); | ||
116 | |||
117 | /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ | 119 | /* Change the kernel's 'tick' value to 10009 usec. (the default is 10000) */ |
118 | tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; | 120 | tick_usec = (LATCH * 1000000) / CLOCK_TICK_RATE; |
119 | 121 | ||
120 | /* Enable Period Interval Timer interrupt */ | 122 | /* Initialize and enable the timer interrupt */ |
121 | at91_sys_write(AT91_ST_IER, AT91_ST_PITS); | 123 | at91rm9200_timer_reset(); |
124 | } | ||
125 | |||
126 | #ifdef CONFIG_PM | ||
127 | static void at91rm9200_timer_suspend(void) | ||
128 | { | ||
129 | /* disable Period Interval Timer interrupt */ | ||
130 | at91_sys_write(AT91_ST_IDR, AT91_ST_PITS); | ||
122 | } | 131 | } |
132 | #else | ||
133 | #define at91rm9200_timer_suspend NULL | ||
134 | #endif | ||
123 | 135 | ||
124 | struct sys_timer at91rm9200_timer = { | 136 | struct sys_timer at91rm9200_timer = { |
125 | .init = at91rm9200_timer_init, | 137 | .init = at91rm9200_timer_init, |
126 | .offset = at91rm9200_gettimeoffset, | 138 | .offset = at91rm9200_gettimeoffset, |
139 | .suspend = at91rm9200_timer_suspend, | ||
140 | .resume = at91rm9200_timer_reset, | ||
127 | }; | 141 | }; |
142 | |||