aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-sa1100
diff options
context:
space:
mode:
authorJochen Friedrich <jochen@scram.de>2011-08-18 16:50:31 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2011-10-17 04:12:42 -0400
commitde0bc0d1b008d1240c03a0bac4f5534f995ab802 (patch)
tree3f3b230d3ff6d3d1f27ceb5525867228668f44c2 /arch/arm/mach-sa1100
parentf24dec9fdafadca53bf9db460da2cbbbfccdb584 (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.h81
-rw-r--r--arch/arm/mach-sa1100/leds-simpad.c7
-rw-r--r--arch/arm/mach-sa1100/simpad.c117
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 94long simpad_get_cs3_ro(void);
70#define VCC_3V_EN 0x0002 // FOR 3.3V PCMCIA 95long simpad_get_cs3_shadow(void);
71#define EN1 0x0004 // This is only for EPROM's 96void simpad_set_cs3_bit(int value);
72#define EN0 0x0008 // Both should be enable for 3.3V or 5V 97void 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 ---*/
90struct simpad_battery { 125struct 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
25extern void set_cs3_bit(int value);
26extern void clear_cs3_bit(int value);
27
28void simpad_leds_event(led_event_t evt) 25void 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
34long cs3_shadow; 35/*
36 * CS3 support
37 */
38
39static long cs3_shadow;
40static spinlock_t cs3_lock;
41static struct gpio_chip cs3_gpio;
42
43long simpad_get_cs3_ro(void)
44{
45 return readl(CS3_BASE);
46}
47EXPORT_SYMBOL(simpad_get_cs3_ro);
35 48
36long get_cs3_shadow(void) 49long simpad_get_cs3_shadow(void)
37{ 50{
38 return cs3_shadow; 51 return cs3_shadow;
39} 52}
53EXPORT_SYMBOL(simpad_get_cs3_shadow);
40 54
41void set_cs3(long value) 55static void __simpad_write_cs3(void)
42{ 56{
43 *(CS3BUSTYPE *)(CS3_BASE) = cs3_shadow = value; 57 writel(cs3_shadow, CS3_BASE);
44} 58}
45 59
46void set_cs3_bit(int value) 60void 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}
69EXPORT_SYMBOL(simpad_set_cs3_bit);
51 70
52void clear_cs3_bit(int value) 71void 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}
80EXPORT_SYMBOL(simpad_clear_cs3_bit);
81
82static 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
58EXPORT_SYMBOL(set_cs3_bit); 92static int cs3_gpio_get(struct gpio_chip *chip, unsigned offset)
59EXPORT_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
99static int cs3_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
100{
101 if (offset > 15)
102 return 0;
103 return -EINVAL;
104};
105
106static 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
61static struct map_desc simpad_io_desc[] __initdata = { 115static 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
172static void simpad_power_off(void) 227static 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,