1 /*
2 * drivers/pcmcia/sa1100_stork.c
3 *
4 Copyright 2001 (C) Ken Gordon
5
6 This is derived from pre-existing drivers/pcmcia/sa1100_?????.c
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License.
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 *
18 * PCMCIA implementation routines for stork
19 *
20 */
21
22 #include <linux/config.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27
28 #include <asm/hardware.h>
29 #include <asm/irq.h>
30 #include "sa1100_generic.h"
31
32 static int debug = 0;
33
34 static struct pcmcia_init sa1100_stork_pcmcia_init;
35
stork_pcmcia_init(struct pcmcia_init * init)36 static int stork_pcmcia_init(struct pcmcia_init *init)
37 {
38 int irq, res;
39 printk("in stork_pcmcia_init\n");
40
41 sa1100_stork_pcmcia_init = *init;
42
43 /* Set transition detect */
44 set_GPIO_IRQ_edge( GPIO_STORK_PCMCIA_A_CARD_DETECT | GPIO_STORK_PCMCIA_B_CARD_DETECT, GPIO_NO_EDGES );
45 set_GPIO_IRQ_edge( GPIO_STORK_PCMCIA_A_RDY| GPIO_STORK_PCMCIA_B_RDY, GPIO_FALLING_EDGE );
46
47 /* Register interrupts */
48 irq = IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT;
49 res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD0", NULL );
50 if( res < 0 ) goto irq_err;
51 irq = IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT;
52 res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD1", NULL );
53 if( res < 0 ) goto irq_err;
54
55 return 2;
56
57 irq_err:
58 printk( KERN_ERR __FUNCTION__ ": Request for IRQ %u failed\n", irq );
59 return -1;
60 }
61
stork_pcmcia_shutdown(void)62 static int stork_pcmcia_shutdown(void)
63 {
64 printk(__FUNCTION__ "\n");
65 /* disable IRQs */
66 free_irq( IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, NULL );
67 free_irq( IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, NULL );
68
69 /* Disable CF bus: */
70 storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
71 storkClearLatchA(STORK_PCMCIA_A_POWER_ON);
72 storkClearLatchA(STORK_PCMCIA_B_POWER_ON);
73 return 0;
74 }
75
stork_pcmcia_socket_state(struct pcmcia_state_array * state_array)76 static int stork_pcmcia_socket_state(struct pcmcia_state_array *state_array)
77 {
78 unsigned long levels;
79
80 if(state_array->size<2) return -1;
81
82 memset(state_array->state, 0,
83 (state_array->size)*sizeof(struct pcmcia_state));
84
85 levels=GPLR;
86
87 if (debug > 1)
88 printk(__FUNCTION__ " GPLR=%x IRQ[1:0]=%x\n", GPLR, (GPLR & (GPIO_STORK_PCMCIA_A_RDY|GPIO_STORK_PCMCIA_B_RDY)));
89 state_array->state[0].detect=((levels & GPIO_STORK_PCMCIA_A_CARD_DETECT)==0)?1:0;
90 state_array->state[0].ready=(levels & GPIO_STORK_PCMCIA_A_RDY)?1:0;
91 state_array->state[0].bvd1= 1;
92 state_array->state[0].bvd2= 1;
93 state_array->state[0].wrprot=0;
94 state_array->state[0].vs_3v=1;
95 state_array->state[0].vs_Xv=0;
96
97 state_array->state[1].detect=((levels & GPIO_STORK_PCMCIA_B_CARD_DETECT)==0)?1:0;
98 state_array->state[1].ready=(levels & GPIO_STORK_PCMCIA_B_RDY)?1:0;
99 state_array->state[1].bvd1=1;
100 state_array->state[1].bvd2=1;
101 state_array->state[1].wrprot=0;
102 state_array->state[1].vs_3v=1;
103 state_array->state[1].vs_Xv=0;
104
105 return 1;
106 }
107
stork_pcmcia_get_irq_info(struct pcmcia_irq_info * info)108 static int stork_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
109 {
110
111 switch (info->sock) {
112 case 0:
113 info->irq=IRQ_GPIO_STORK_PCMCIA_A_RDY;
114 break;
115 case 1:
116 info->irq=IRQ_GPIO_STORK_PCMCIA_B_RDY;
117 break;
118 default:
119 return -1;
120 }
121 return 0;
122 }
123
stork_pcmcia_configure_socket(const struct pcmcia_configure * configure)124 static int stork_pcmcia_configure_socket(const struct pcmcia_configure *configure)
125 {
126 int card = configure->sock;
127 unsigned long flags;
128
129 int DETECT, RDY, POWER, RESET;
130
131 if (card > 1) return -1;
132
133 printk(__FUNCTION__ ": socket=%d vcc=%d vpp=%d reset=%d\n",
134 card, configure->vcc, configure->vpp, configure->reset);
135
136 save_flags_cli(flags);
137
138 if (card == 0) {
139 DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT;
140 RDY = GPIO_STORK_PCMCIA_A_RDY;
141 POWER = STORK_PCMCIA_A_POWER_ON;
142 RESET = STORK_PCMCIA_A_RESET;
143 } else {
144 DETECT = GPIO_STORK_PCMCIA_B_CARD_DETECT;
145 RDY = GPIO_STORK_PCMCIA_B_RDY;
146 POWER = STORK_PCMCIA_B_POWER_ON;
147 RESET = STORK_PCMCIA_B_RESET;
148 }
149
150 /*
151 if (storkTestGPIO(DETECT)) {
152 printk("no card detected - but resetting anyway\r\n");
153 }
154 */
155 switch (configure->vcc) {
156 case 0:
157 /* storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); */
158 storkClearLatchA(POWER);
159 break;
160
161 case 50:
162 case 33:
163 storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
164 storkSetLatchA(POWER);
165 break;
166
167 default:
168 printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
169 configure->vcc);
170 restore_flags(flags);
171 return -1;
172 }
173
174 if (configure->reset)
175 storkSetLatchB(RESET);
176 else
177 storkClearLatchB(RESET);
178
179 restore_flags(flags);
180
181 /* silently ignore vpp and speaker enables. */
182
183 printk(__FUNCTION__ ": finished\n");
184
185 return 0;
186 }
187
stork_pcmcia_socket_init(int sock)188 static int stork_pcmcia_socket_init(int sock)
189 {
190 storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
191
192 if (sock == 0)
193 set_GPIO_IRQ_edge(GPIO_STORK_PCMCIA_A_CARD_DETECT, GPIO_BOTH_EDGES);
194 else if (sock == 1)
195 set_GPIO_IRQ_edge(GPIO_STORK_PCMCIA_B_CARD_DETECT, GPIO_BOTH_EDGES);
196
197 return 0;
198 }
199
stork_pcmcia_socket_suspend(int sock)200 static int stork_pcmcia_socket_suspend(int sock)
201 {
202 if (sock == 0)
203 set_GPIO_IRQ_edge(GPIO_STORK_PCMCIA_A_CARD_DETECT, GPIO_NO_EDGES);
204 else if (sock == 1) {
205 set_GPIO_IRQ_edge(GPIO_STORK_PCMCIA_B_CARD_DETECT, GPIO_NO_EDGES);
206
207 /*
208 * Hack!
209 */
210 storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
211 }
212
213 return 0;
214 }
215
216 struct pcmcia_low_level stork_pcmcia_ops = {
217 init: stork_pcmcia_init,
218 shutdown: stork_pcmcia_shutdown,
219 socket_state: stork_pcmcia_socket_state,
220 get_irq_info: stork_pcmcia_get_irq_info,
221 configure_socket: stork_pcmcia_configure_socket,
222
223 socket_init: stork_pcmcia_socket_init,
224 socket_suspend: stork_pcmcia_socket_suspend,
225 };
226