diff options
author | Jochen Friedrich <jochen@scram.de> | 2011-08-18 16:50:31 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-10-17 04:12:42 -0400 |
commit | de0bc0d1b008d1240c03a0bac4f5534f995ab802 (patch) | |
tree | 3f3b230d3ff6d3d1f27ceb5525867228668f44c2 /arch/arm/mach-sa1100 | |
parent | f24dec9fdafadca53bf9db460da2cbbbfccdb584 (diff) |
ARM: 7024/1: simpad: Cleanup CS3 accessors.
- prepend CS3 accessors by simpad_ to indicate they
are specific to simpad devices.
- use spinlock to protect shadow register.
- implement 8 read-only pins.
- use readl/writel macros so barriers are used where
necessary.
- register CS3 as GPIO controller with 24 pins
(16 output only and 8 input only).
- fix PCMCIA driver to access the read-only pins
rather than the shadow register for status bits.
Signed-off-by: Jochen Friedrich <jochen@scram.de>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/mach-sa1100')
-rw-r--r-- | arch/arm/mach-sa1100/include/mach/simpad.h | 81 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/leds-simpad.c | 7 | ||||
-rw-r--r-- | arch/arm/mach-sa1100/simpad.c | 117 |
3 files changed, 153 insertions, 52 deletions
diff --git a/arch/arm/mach-sa1100/include/mach/simpad.h b/arch/arm/mach-sa1100/include/mach/simpad.h index 231550da7db8..db28118103eb 100644 --- a/arch/arm/mach-sa1100/include/mach/simpad.h +++ b/arch/arm/mach-sa1100/include/mach/simpad.h | |||
@@ -61,32 +61,67 @@ | |||
61 | #define SIMPAD_UCB1X00_GPIO_HEADSET (SIMPAD_UCB1X00_GPIO_BASE + 8) | 61 | #define SIMPAD_UCB1X00_GPIO_HEADSET (SIMPAD_UCB1X00_GPIO_BASE + 8) |
62 | #define SIMPAD_UCB1X00_GPIO_SPEAKER (SIMPAD_UCB1X00_GPIO_BASE + 9) | 62 | #define SIMPAD_UCB1X00_GPIO_SPEAKER (SIMPAD_UCB1X00_GPIO_BASE + 9) |
63 | 63 | ||
64 | // CS3 Latch is write only, a shadow is necessary | 64 | /*--- CS3 Latch ---*/ |
65 | #define SIMPAD_CS3_GPIO_BASE (GPIO_MAX + 11) | ||
66 | #define SIMPAD_CS3_VCC_5V_EN (SIMPAD_CS3_GPIO_BASE) | ||
67 | #define SIMPAD_CS3_VCC_3V_EN (SIMPAD_CS3_GPIO_BASE + 1) | ||
68 | #define SIMPAD_CS3_EN1 (SIMPAD_CS3_GPIO_BASE + 2) | ||
69 | #define SIMPAD_CS3_EN0 (SIMPAD_CS3_GPIO_BASE + 3) | ||
70 | #define SIMPAD_CS3_DISPLAY_ON (SIMPAD_CS3_GPIO_BASE + 4) | ||
71 | #define SIMPAD_CS3_PCMCIA_BUFF_DIS (SIMPAD_CS3_GPIO_BASE + 5) | ||
72 | #define SIMPAD_CS3_MQ_RESET (SIMPAD_CS3_GPIO_BASE + 6) | ||
73 | #define SIMPAD_CS3_PCMCIA_RESET (SIMPAD_CS3_GPIO_BASE + 7) | ||
74 | #define SIMPAD_CS3_DECT_POWER_ON (SIMPAD_CS3_GPIO_BASE + 8) | ||
75 | #define SIMPAD_CS3_IRDA_SD (SIMPAD_CS3_GPIO_BASE + 9) | ||
76 | #define SIMPAD_CS3_RS232_ON (SIMPAD_CS3_GPIO_BASE + 10) | ||
77 | #define SIMPAD_CS3_SD_MEDIAQ (SIMPAD_CS3_GPIO_BASE + 11) | ||
78 | #define SIMPAD_CS3_LED2_ON (SIMPAD_CS3_GPIO_BASE + 12) | ||
79 | #define SIMPAD_CS3_IRDA_MODE (SIMPAD_CS3_GPIO_BASE + 13) | ||
80 | #define SIMPAD_CS3_ENABLE_5V (SIMPAD_CS3_GPIO_BASE + 14) | ||
81 | #define SIMPAD_CS3_RESET_SIMCARD (SIMPAD_CS3_GPIO_BASE + 15) | ||
82 | |||
83 | #define SIMPAD_CS3_PCMCIA_BVD1 (SIMPAD_CS3_GPIO_BASE + 16) | ||
84 | #define SIMPAD_CS3_PCMCIA_BVD2 (SIMPAD_CS3_GPIO_BASE + 17) | ||
85 | #define SIMPAD_CS3_PCMCIA_VS1 (SIMPAD_CS3_GPIO_BASE + 18) | ||
86 | #define SIMPAD_CS3_PCMCIA_VS2 (SIMPAD_CS3_GPIO_BASE + 19) | ||
87 | #define SIMPAD_CS3_LOCK_IND (SIMPAD_CS3_GPIO_BASE + 20) | ||
88 | #define SIMPAD_CS3_CHARGING_STATE (SIMPAD_CS3_GPIO_BASE + 21) | ||
89 | #define SIMPAD_CS3_PCMCIA_SHORT (SIMPAD_CS3_GPIO_BASE + 22) | ||
90 | #define SIMPAD_CS3_GPIO_23 (SIMPAD_CS3_GPIO_BASE + 23) | ||
65 | 91 | ||
66 | #define CS3BUSTYPE unsigned volatile long | ||
67 | #define CS3_BASE 0xf1000000 | 92 | #define CS3_BASE 0xf1000000 |
68 | 93 | ||
69 | #define VCC_5V_EN 0x0001 // For 5V PCMCIA | 94 | long simpad_get_cs3_ro(void); |
70 | #define VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA | 95 | long simpad_get_cs3_shadow(void); |
71 | #define EN1 0x0004 // This is only for EPROM's | 96 | void simpad_set_cs3_bit(int value); |
72 | #define EN0 0x0008 // Both should be enable for 3.3V or 5V | 97 | void simpad_clear_cs3_bit(int value); |
73 | #define DISPLAY_ON 0x0010 | 98 | |
74 | #define PCMCIA_BUFF_DIS 0x0020 | 99 | #define VCC_5V_EN 0x0001 /* For 5V PCMCIA */ |
75 | #define MQ_RESET 0x0040 | 100 | #define VCC_3V_EN 0x0002 /* FOR 3.3V PCMCIA */ |
76 | #define PCMCIA_RESET 0x0080 | 101 | #define EN1 0x0004 /* This is only for EPROM's */ |
77 | #define DECT_POWER_ON 0x0100 | 102 | #define EN0 0x0008 /* Both should be enable for 3.3V or 5V */ |
78 | #define IRDA_SD 0x0200 // Shutdown for powersave | 103 | #define DISPLAY_ON 0x0010 |
79 | #define RS232_ON 0x0400 | 104 | #define PCMCIA_BUFF_DIS 0x0020 |
80 | #define SD_MEDIAQ 0x0800 // Shutdown for powersave | 105 | #define MQ_RESET 0x0040 |
81 | #define LED2_ON 0x1000 | 106 | #define PCMCIA_RESET 0x0080 |
82 | #define IRDA_MODE 0x2000 // Fast/Slow IrDA mode | 107 | #define DECT_POWER_ON 0x0100 |
83 | #define ENABLE_5V 0x4000 // Enable 5V circuit | 108 | #define IRDA_SD 0x0200 /* Shutdown for powersave */ |
84 | #define RESET_SIMCARD 0x8000 | 109 | #define RS232_ON 0x0400 |
85 | 110 | #define SD_MEDIAQ 0x0800 /* Shutdown for powersave */ | |
86 | #define RS232_ENABLE 0x0440 | 111 | #define LED2_ON 0x1000 |
87 | #define PCMCIAMASK 0x402f | 112 | #define IRDA_MODE 0x2000 /* Fast/Slow IrDA mode */ |
88 | 113 | #define ENABLE_5V 0x4000 /* Enable 5V circuit */ | |
89 | 114 | #define RESET_SIMCARD 0x8000 | |
115 | |||
116 | #define PCMCIA_BVD1 0x01 | ||
117 | #define PCMCIA_BVD2 0x02 | ||
118 | #define PCMCIA_VS1 0x04 | ||
119 | #define PCMCIA_VS2 0x08 | ||
120 | #define LOCK_IND 0x10 | ||
121 | #define CHARGING_STATE 0x20 | ||
122 | #define PCMCIA_SHORT 0x40 | ||
123 | |||
124 | /*--- Battery ---*/ | ||
90 | struct simpad_battery { | 125 | struct simpad_battery { |
91 | unsigned char ac_status; /* line connected yes/no */ | 126 | unsigned char ac_status; /* line connected yes/no */ |
92 | unsigned char status; /* battery loading yes/no */ | 127 | unsigned char status; /* battery loading yes/no */ |
diff --git a/arch/arm/mach-sa1100/leds-simpad.c b/arch/arm/mach-sa1100/leds-simpad.c index d50f4eeaa12e..d25784cc96e6 100644 --- a/arch/arm/mach-sa1100/leds-simpad.c +++ b/arch/arm/mach-sa1100/leds-simpad.c | |||
@@ -22,9 +22,6 @@ static unsigned int hw_led_state; | |||
22 | #define LED_GREEN (1) | 22 | #define LED_GREEN (1) |
23 | #define LED_MASK (1) | 23 | #define LED_MASK (1) |
24 | 24 | ||
25 | extern void set_cs3_bit(int value); | ||
26 | extern void clear_cs3_bit(int value); | ||
27 | |||
28 | void simpad_leds_event(led_event_t evt) | 25 | void simpad_leds_event(led_event_t evt) |
29 | { | 26 | { |
30 | switch (evt) | 27 | switch (evt) |
@@ -93,8 +90,8 @@ void simpad_leds_event(led_event_t evt) | |||
93 | } | 90 | } |
94 | 91 | ||
95 | if (led_state & LED_STATE_ENABLED) | 92 | if (led_state & LED_STATE_ENABLED) |
96 | set_cs3_bit(LED2_ON); | 93 | simpad_set_cs3_bit(LED2_ON); |
97 | else | 94 | else |
98 | clear_cs3_bit(LED2_ON); | 95 | simpad_clear_cs3_bit(LED2_ON); |
99 | } | 96 | } |
100 | 97 | ||
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c index 718b802bbff3..c3c66b0d6b6e 100644 --- a/arch/arm/mach-sa1100/simpad.c +++ b/arch/arm/mach-sa1100/simpad.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/mtd/mtd.h> | 13 | #include <linux/mtd/mtd.h> |
14 | #include <linux/mtd/partitions.h> | 14 | #include <linux/mtd/partitions.h> |
15 | #include <linux/io.h> | 15 | #include <linux/io.h> |
16 | #include <linux/gpio.h> | ||
16 | 17 | ||
17 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
18 | #include <mach/hardware.h> | 19 | #include <mach/hardware.h> |
@@ -31,32 +32,85 @@ | |||
31 | 32 | ||
32 | #include "generic.h" | 33 | #include "generic.h" |
33 | 34 | ||
34 | long cs3_shadow; | 35 | /* |
36 | * CS3 support | ||
37 | */ | ||
38 | |||
39 | static long cs3_shadow; | ||
40 | static spinlock_t cs3_lock; | ||
41 | static struct gpio_chip cs3_gpio; | ||
42 | |||
43 | long simpad_get_cs3_ro(void) | ||
44 | { | ||
45 | return readl(CS3_BASE); | ||
46 | } | ||
47 | EXPORT_SYMBOL(simpad_get_cs3_ro); | ||
35 | 48 | ||
36 | long get_cs3_shadow(void) | 49 | long simpad_get_cs3_shadow(void) |
37 | { | 50 | { |
38 | return cs3_shadow; | 51 | return cs3_shadow; |
39 | } | 52 | } |
53 | EXPORT_SYMBOL(simpad_get_cs3_shadow); | ||
40 | 54 | ||
41 | void set_cs3(long value) | 55 | static void __simpad_write_cs3(void) |
42 | { | 56 | { |
43 | *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value; | 57 | writel(cs3_shadow, CS3_BASE); |
44 | } | 58 | } |
45 | 59 | ||
46 | void set_cs3_bit(int value) | 60 | void simpad_set_cs3_bit(int value) |
47 | { | 61 | { |
62 | unsigned long flags; | ||
63 | |||
64 | spin_lock_irqsave(&cs3_lock, flags); | ||
48 | cs3_shadow |= value; | 65 | cs3_shadow |= value; |
49 | *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; | 66 | __simpad_write_cs3(); |
67 | spin_unlock_irqrestore(&cs3_lock, flags); | ||
50 | } | 68 | } |
69 | EXPORT_SYMBOL(simpad_set_cs3_bit); | ||
51 | 70 | ||
52 | void clear_cs3_bit(int value) | 71 | void simpad_clear_cs3_bit(int value) |
53 | { | 72 | { |
73 | unsigned long flags; | ||
74 | |||
75 | spin_lock_irqsave(&cs3_lock, flags); | ||
54 | cs3_shadow &= ~value; | 76 | cs3_shadow &= ~value; |
55 | *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow; | 77 | __simpad_write_cs3(); |
78 | spin_unlock_irqrestore(&cs3_lock, flags); | ||
56 | } | 79 | } |
80 | EXPORT_SYMBOL(simpad_clear_cs3_bit); | ||
81 | |||
82 | static void cs3_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||
83 | { | ||
84 | if (offset > 15) | ||
85 | return; | ||
86 | if (value) | ||
87 | simpad_set_cs3_bit(1 << offset); | ||
88 | else | ||
89 | simpad_clear_cs3_bit(1 << offset); | ||
90 | }; | ||
57 | 91 | ||
58 | EXPORT_SYMBOL(set_cs3_bit); | 92 | static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset) |
59 | EXPORT_SYMBOL(clear_cs3_bit); | 93 | { |
94 | if (offset > 15) | ||
95 | return simpad_get_cs3_ro() & (1 << (offset - 16)); | ||
96 | return simpad_get_cs3_shadow() & (1 << offset); | ||
97 | }; | ||
98 | |||
99 | static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
100 | { | ||
101 | if (offset > 15) | ||
102 | return 0; | ||
103 | return -EINVAL; | ||
104 | }; | ||
105 | |||
106 | static int cs3_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
107 | int value) | ||
108 | { | ||
109 | if (offset > 15) | ||
110 | return -EINVAL; | ||
111 | cs3_gpio_set(chip, offset, value); | ||
112 | return 0; | ||
113 | }; | ||
60 | 114 | ||
61 | static struct map_desc simpad_io_desc[] __initdata = { | 115 | static struct map_desc simpad_io_desc[] __initdata = { |
62 | { /* MQ200 */ | 116 | { /* MQ200 */ |
@@ -64,9 +118,9 @@ static struct map_desc simpad_io_desc[] __initdata = { | |||
64 | .pfn = __phys_to_pfn(0x4b800000), | 118 | .pfn = __phys_to_pfn(0x4b800000), |
65 | .length = 0x00800000, | 119 | .length = 0x00800000, |
66 | .type = MT_DEVICE | 120 | .type = MT_DEVICE |
67 | }, { /* Paules CS3, write only */ | 121 | }, { /* Simpad CS3 */ |
68 | .virtual = 0xf1000000, | 122 | .virtual = CS3_BASE, |
69 | .pfn = __phys_to_pfn(0x18000000), | 123 | .pfn = __phys_to_pfn(SA1100_CS3_PHYS), |
70 | .length = 0x00100000, | 124 | .length = 0x00100000, |
71 | .type = MT_DEVICE | 125 | .type = MT_DEVICE |
72 | }, | 126 | }, |
@@ -78,12 +132,12 @@ static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate) | |||
78 | if (port->mapbase == (u_int)&Ser1UTCR0) { | 132 | if (port->mapbase == (u_int)&Ser1UTCR0) { |
79 | if (state) | 133 | if (state) |
80 | { | 134 | { |
81 | clear_cs3_bit(RS232_ON); | 135 | simpad_clear_cs3_bit(RS232_ON); |
82 | clear_cs3_bit(DECT_POWER_ON); | 136 | simpad_clear_cs3_bit(DECT_POWER_ON); |
83 | }else | 137 | }else |
84 | { | 138 | { |
85 | set_cs3_bit(RS232_ON); | 139 | simpad_set_cs3_bit(RS232_ON); |
86 | set_cs3_bit(DECT_POWER_ON); | 140 | simpad_set_cs3_bit(DECT_POWER_ON); |
87 | } | 141 | } |
88 | } | 142 | } |
89 | } | 143 | } |
@@ -143,9 +197,10 @@ static void __init simpad_map_io(void) | |||
143 | 197 | ||
144 | iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc)); | 198 | iotable_init(simpad_io_desc, ARRAY_SIZE(simpad_io_desc)); |
145 | 199 | ||
146 | set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON | | 200 | /* Initialize CS3 */ |
147 | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); | 201 | cs3_shadow = (EN1 | EN0 | LED2_ON | DISPLAY_ON | |
148 | 202 | RS232_ON | ENABLE_5V | RESET_SIMCARD | DECT_POWER_ON); | |
203 | __simpad_write_cs3(); /* Spinlocks not yet initialized */ | ||
149 | 204 | ||
150 | sa1100_register_uart_fns(&simpad_port_fns); | 205 | sa1100_register_uart_fns(&simpad_port_fns); |
151 | sa1100_register_uart(0, 3); /* serial interface */ | 206 | sa1100_register_uart(0, 3); /* serial interface */ |
@@ -171,13 +226,14 @@ static void __init simpad_map_io(void) | |||
171 | 226 | ||
172 | static void simpad_power_off(void) | 227 | static void simpad_power_off(void) |
173 | { | 228 | { |
174 | local_irq_disable(); // was cli | 229 | local_irq_disable(); |
175 | set_cs3(0x800); /* only SD_MEDIAQ */ | 230 | cs3_shadow = SD_MEDIAQ; |
231 | __simpad_write_cs3(); /* Bypass spinlock here */ | ||
176 | 232 | ||
177 | /* disable internal oscillator, float CS lines */ | 233 | /* disable internal oscillator, float CS lines */ |
178 | PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); | 234 | PCFR = (PCFR_OPDE | PCFR_FP | PCFR_FS); |
179 | /* enable wake-up on GPIO0 (Assabet...) */ | 235 | /* enable wake-up on GPIO0 */ |
180 | PWER = GFER = GRER = 1; | 236 | PWER = GFER = GRER = PWER_GPIO0; |
181 | /* | 237 | /* |
182 | * set scratchpad to zero, just in case it is used as a | 238 | * set scratchpad to zero, just in case it is used as a |
183 | * restart address by the bootloader. | 239 | * restart address by the bootloader. |
@@ -212,6 +268,19 @@ static int __init simpad_init(void) | |||
212 | { | 268 | { |
213 | int ret; | 269 | int ret; |
214 | 270 | ||
271 | spin_lock_init(&cs3_lock); | ||
272 | |||
273 | cs3_gpio.label = "simpad_cs3"; | ||
274 | cs3_gpio.base = SIMPAD_CS3_GPIO_BASE; | ||
275 | cs3_gpio.ngpio = 24; | ||
276 | cs3_gpio.set = cs3_gpio_set; | ||
277 | cs3_gpio.get = cs3_gpio_get; | ||
278 | cs3_gpio.direction_input = cs3_gpio_direction_input; | ||
279 | cs3_gpio.direction_output = cs3_gpio_direction_output; | ||
280 | ret = gpiochip_add(&cs3_gpio); | ||
281 | if (ret) | ||
282 | printk(KERN_WARNING "simpad: Unable to register cs3 GPIO device"); | ||
283 | |||
215 | pm_power_off = simpad_power_off; | 284 | pm_power_off = simpad_power_off; |
216 | 285 | ||
217 | sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, | 286 | sa11x0_register_mtd(&simpad_flash_data, simpad_flash_resources, |