diff options
Diffstat (limited to 'drivers/pcmcia/sa1100_h3600.c')
-rw-r--r-- | drivers/pcmcia/sa1100_h3600.c | 140 |
1 files changed, 116 insertions, 24 deletions
diff --git a/drivers/pcmcia/sa1100_h3600.c b/drivers/pcmcia/sa1100_h3600.c index 0cc3748f3758..56329ad575a9 100644 --- a/drivers/pcmcia/sa1100_h3600.c +++ b/drivers/pcmcia/sa1100_h3600.c | |||
@@ -10,47 +10,139 @@ | |||
10 | #include <linux/interrupt.h> | 10 | #include <linux/interrupt.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
13 | #include <linux/gpio.h> | ||
13 | 14 | ||
14 | #include <mach/hardware.h> | 15 | #include <mach/hardware.h> |
15 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
16 | #include <asm/mach-types.h> | 17 | #include <asm/mach-types.h> |
17 | #include <mach/h3600.h> | 18 | #include <mach/h3xxx.h> |
18 | 19 | ||
19 | #include "sa1100_generic.h" | 20 | #include "sa1100_generic.h" |
20 | 21 | ||
21 | static struct pcmcia_irqs irqs[] = { | 22 | static struct pcmcia_irqs irqs[] = { |
22 | { 0, IRQ_GPIO_H3600_PCMCIA_CD0, "PCMCIA CD0" }, | 23 | { .sock = 0, .str = "PCMCIA CD0" }, /* .irq will be filled later */ |
23 | { 1, IRQ_GPIO_H3600_PCMCIA_CD1, "PCMCIA CD1" } | 24 | { .sock = 1, .str = "PCMCIA CD1" } |
24 | }; | 25 | }; |
25 | 26 | ||
26 | static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | 27 | static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt) |
27 | { | 28 | { |
28 | skt->irq = skt->nr ? IRQ_GPIO_H3600_PCMCIA_IRQ1 | 29 | int err; |
29 | : IRQ_GPIO_H3600_PCMCIA_IRQ0; | ||
30 | 30 | ||
31 | switch (skt->nr) { | ||
32 | case 0: | ||
33 | err = gpio_request(H3XXX_GPIO_PCMCIA_IRQ0, "PCMCIA IRQ0"); | ||
34 | if (err) | ||
35 | goto err00; | ||
36 | err = gpio_direction_input(H3XXX_GPIO_PCMCIA_IRQ0); | ||
37 | if (err) | ||
38 | goto err01; | ||
39 | skt->socket.pci_irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_IRQ0); | ||
40 | |||
41 | err = gpio_request(H3XXX_GPIO_PCMCIA_CD0, "PCMCIA CD0"); | ||
42 | if (err) | ||
43 | goto err01; | ||
44 | err = gpio_direction_input(H3XXX_GPIO_PCMCIA_CD0); | ||
45 | if (err) | ||
46 | goto err02; | ||
47 | irqs[0].irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_CD0); | ||
48 | |||
49 | err = gpio_request(H3XXX_EGPIO_OPT_NVRAM_ON, "OPT NVRAM ON"); | ||
50 | if (err) | ||
51 | goto err02; | ||
52 | err = gpio_direction_output(H3XXX_EGPIO_OPT_NVRAM_ON, 0); | ||
53 | if (err) | ||
54 | goto err03; | ||
55 | err = gpio_request(H3XXX_EGPIO_OPT_ON, "OPT ON"); | ||
56 | if (err) | ||
57 | goto err03; | ||
58 | err = gpio_direction_output(H3XXX_EGPIO_OPT_ON, 0); | ||
59 | if (err) | ||
60 | goto err04; | ||
61 | err = gpio_request(H3XXX_EGPIO_OPT_RESET, "OPT RESET"); | ||
62 | if (err) | ||
63 | goto err04; | ||
64 | err = gpio_direction_output(H3XXX_EGPIO_OPT_RESET, 0); | ||
65 | if (err) | ||
66 | goto err05; | ||
67 | err = gpio_request(H3XXX_EGPIO_CARD_RESET, "PCMCIA CARD RESET"); | ||
68 | if (err) | ||
69 | goto err05; | ||
70 | err = gpio_direction_output(H3XXX_EGPIO_CARD_RESET, 0); | ||
71 | if (err) | ||
72 | goto err06; | ||
73 | err = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
74 | if (err) | ||
75 | goto err06; | ||
76 | break; | ||
77 | case 1: | ||
78 | err = gpio_request(H3XXX_GPIO_PCMCIA_IRQ1, "PCMCIA IRQ1"); | ||
79 | if (err) | ||
80 | goto err10; | ||
81 | err = gpio_direction_input(H3XXX_GPIO_PCMCIA_IRQ1); | ||
82 | if (err) | ||
83 | goto err11; | ||
84 | skt->socket.pci_irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_IRQ1); | ||
85 | |||
86 | err = gpio_request(H3XXX_GPIO_PCMCIA_CD1, "PCMCIA CD1"); | ||
87 | if (err) | ||
88 | goto err11; | ||
89 | err = gpio_direction_input(H3XXX_GPIO_PCMCIA_CD1); | ||
90 | if (err) | ||
91 | goto err12; | ||
92 | irqs[1].irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_CD1); | ||
93 | |||
94 | err = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | ||
95 | if (err) | ||
96 | goto err12; | ||
97 | break; | ||
98 | } | ||
99 | return 0; | ||
31 | 100 | ||
32 | return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); | 101 | err06: gpio_free(H3XXX_EGPIO_CARD_RESET); |
102 | err05: gpio_free(H3XXX_EGPIO_OPT_RESET); | ||
103 | err04: gpio_free(H3XXX_EGPIO_OPT_ON); | ||
104 | err03: gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); | ||
105 | err02: gpio_free(H3XXX_GPIO_PCMCIA_CD0); | ||
106 | err01: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); | ||
107 | err00: return err; | ||
108 | |||
109 | err12: gpio_free(H3XXX_GPIO_PCMCIA_CD0); | ||
110 | err11: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); | ||
111 | err10: return err; | ||
33 | } | 112 | } |
34 | 113 | ||
35 | static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | 114 | static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) |
36 | { | 115 | { |
37 | soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); | 116 | soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); |
38 | 117 | ||
39 | /* Disable CF bus: */ | 118 | switch (skt->nr) { |
40 | assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 0); | 119 | case 0: |
41 | assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 0); | 120 | /* Disable CF bus: */ |
42 | assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 1); | 121 | gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0); |
122 | gpio_set_value(H3XXX_EGPIO_OPT_ON, 0); | ||
123 | gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1); | ||
124 | |||
125 | gpio_free(H3XXX_EGPIO_CARD_RESET); | ||
126 | gpio_free(H3XXX_EGPIO_OPT_RESET); | ||
127 | gpio_free(H3XXX_EGPIO_OPT_ON); | ||
128 | gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); | ||
129 | gpio_free(H3XXX_GPIO_PCMCIA_CD0); | ||
130 | gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); | ||
131 | break; | ||
132 | case 1: | ||
133 | gpio_free(H3XXX_GPIO_PCMCIA_CD1); | ||
134 | gpio_free(H3XXX_GPIO_PCMCIA_IRQ1); | ||
135 | break; | ||
136 | } | ||
43 | } | 137 | } |
44 | 138 | ||
45 | static void | 139 | static void |
46 | h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) | 140 | h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) |
47 | { | 141 | { |
48 | unsigned long levels = GPLR; | ||
49 | |||
50 | switch (skt->nr) { | 142 | switch (skt->nr) { |
51 | case 0: | 143 | case 0: |
52 | state->detect = levels & GPIO_H3600_PCMCIA_CD0 ? 0 : 1; | 144 | state->detect = !gpio_get_value(H3XXX_GPIO_PCMCIA_CD0); |
53 | state->ready = levels & GPIO_H3600_PCMCIA_IRQ0 ? 1 : 0; | 145 | state->ready = !!gpio_get_value(H3XXX_GPIO_PCMCIA_IRQ0); |
54 | state->bvd1 = 0; | 146 | state->bvd1 = 0; |
55 | state->bvd2 = 0; | 147 | state->bvd2 = 0; |
56 | state->wrprot = 0; /* Not available on H3600. */ | 148 | state->wrprot = 0; /* Not available on H3600. */ |
@@ -59,8 +151,8 @@ h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *st | |||
59 | break; | 151 | break; |
60 | 152 | ||
61 | case 1: | 153 | case 1: |
62 | state->detect = levels & GPIO_H3600_PCMCIA_CD1 ? 0 : 1; | 154 | state->detect = !gpio_get_value(H3XXX_GPIO_PCMCIA_CD1); |
63 | state->ready = levels & GPIO_H3600_PCMCIA_IRQ1 ? 1 : 0; | 155 | state->ready = !!gpio_get_value(H3XXX_GPIO_PCMCIA_IRQ1); |
64 | state->bvd1 = 0; | 156 | state->bvd1 = 0; |
65 | state->bvd2 = 0; | 157 | state->bvd2 = 0; |
66 | state->wrprot = 0; /* Not available on H3600. */ | 158 | state->wrprot = 0; /* Not available on H3600. */ |
@@ -79,7 +171,7 @@ h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_ | |||
79 | return -1; | 171 | return -1; |
80 | } | 172 | } |
81 | 173 | ||
82 | assign_h3600_egpio(IPAQ_EGPIO_CARD_RESET, !!(state->flags & SS_RESET)); | 174 | gpio_set_value(H3XXX_EGPIO_CARD_RESET, !!(state->flags & SS_RESET)); |
83 | 175 | ||
84 | /* Silently ignore Vpp, output enable, speaker enable. */ | 176 | /* Silently ignore Vpp, output enable, speaker enable. */ |
85 | 177 | ||
@@ -89,9 +181,9 @@ h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_ | |||
89 | static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | 181 | static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) |
90 | { | 182 | { |
91 | /* Enable CF bus: */ | 183 | /* Enable CF bus: */ |
92 | assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 1); | 184 | gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 1); |
93 | assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 1); | 185 | gpio_set_value(H3XXX_EGPIO_OPT_ON, 1); |
94 | assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 0); | 186 | gpio_set_value(H3XXX_EGPIO_OPT_RESET, 0); |
95 | 187 | ||
96 | msleep(10); | 188 | msleep(10); |
97 | 189 | ||
@@ -109,10 +201,10 @@ static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | |||
109 | * socket 0 then socket 1. | 201 | * socket 0 then socket 1. |
110 | */ | 202 | */ |
111 | if (skt->nr == 1) { | 203 | if (skt->nr == 1) { |
112 | assign_h3600_egpio(IPAQ_EGPIO_OPT_ON, 0); | 204 | gpio_set_value(H3XXX_EGPIO_OPT_ON, 0); |
113 | assign_h3600_egpio(IPAQ_EGPIO_OPT_NVRAM_ON, 0); | 205 | gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0); |
114 | /* hmm, does this suck power? */ | 206 | /* hmm, does this suck power? */ |
115 | assign_h3600_egpio(IPAQ_EGPIO_OPT_RESET, 1); | 207 | gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1); |
116 | } | 208 | } |
117 | } | 209 | } |
118 | 210 | ||
@@ -131,7 +223,7 @@ int __init pcmcia_h3600_init(struct device *dev) | |||
131 | { | 223 | { |
132 | int ret = -ENODEV; | 224 | int ret = -ENODEV; |
133 | 225 | ||
134 | if (machine_is_h3600()) | 226 | if (machine_is_h3600() || machine_is_h3100()) |
135 | ret = sa11xx_drv_pcmcia_probe(dev, &h3600_pcmcia_ops, 0, 2); | 227 | ret = sa11xx_drv_pcmcia_probe(dev, &h3600_pcmcia_ops, 0, 2); |
136 | 228 | ||
137 | return ret; | 229 | return ret; |