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