1 /*
2  * drivers/pcmcia/sa1100_cerf.c
3  *
4  * PCMCIA implementation routines for CerfBoard
5  * Based off the Assabet.
6  *
7  */
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 
11 #include <asm/hardware.h>
12 #include <asm/irq.h>
13 #include "sa1100_generic.h"
14 
15 #ifdef CONFIG_SA1100_CERF_CPLD
16 #define CERF_SOCKET	0
17 #else
18 #define CERF_SOCKET	1
19 #endif
20 
21 static struct irqs {
22 	int irq;
23 	unsigned int gpio;
24 	const char *str;
25 } irqs[] = {
26 	{ IRQ_GPIO_CF_CD,   GPIO_CF_CD,   "CF_CD"   },
27 	{ IRQ_GPIO_CF_BVD2, GPIO_CF_BVD2, "CF_BVD2" },
28 	{ IRQ_GPIO_CF_BVD1, GPIO_CF_BVD1, "CF_BVD1" }
29 };
30 
cerf_pcmcia_init(struct pcmcia_init * init)31 static int cerf_pcmcia_init(struct pcmcia_init *init)
32 {
33   int i, res;
34 
35   set_GPIO_IRQ_edge( GPIO_CF_IRQ, GPIO_FALLING_EDGE );
36 
37   for (i = 0; i < ARRAY_SIZE(irqs); i++) {
38     set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
39     res = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
40 		      irqs[i].str, NULL);
41     if (res)
42       goto irq_err;
43   }
44 
45   return 2;
46 
47  irq_err:
48   printk(KERN_ERR "%s: Request for IRQ%d failed\n", __FUNCTION__, irqs[i].irq);
49 
50   while (i--)
51     free_irq(irqs[i].irq, NULL);
52 
53   return -1;
54 }
55 
cerf_pcmcia_shutdown(void)56 static int cerf_pcmcia_shutdown(void)
57 {
58   int i;
59 
60   for (i = 0; i < ARRAY_SIZE(irqs); i++)
61     free_irq(irqs[i].irq, NULL);
62 
63   return 0;
64 }
65 
cerf_pcmcia_socket_state(struct pcmcia_state_array * state_array)66 static int cerf_pcmcia_socket_state(struct pcmcia_state_array
67 				       *state_array){
68   unsigned long levels;
69   int i = CERF_SOCKET;
70 
71   if(state_array->size<2) return -1;
72 
73   levels=GPLR;
74 
75   state_array->state[i].detect=((levels & GPIO_CF_CD)==0)?1:0;
76   state_array->state[i].ready=(levels & GPIO_CF_IRQ)?1:0;
77   state_array->state[i].bvd1=(levels & GPIO_CF_BVD1)?1:0;
78   state_array->state[i].bvd2=(levels & GPIO_CF_BVD2)?1:0;
79   state_array->state[i].wrprot=0;
80   state_array->state[i].vs_3v=1;
81   state_array->state[i].vs_Xv=0;
82 
83   return 1;
84 }
85 
cerf_pcmcia_get_irq_info(struct pcmcia_irq_info * info)86 static int cerf_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
87 
88   if(info->sock>1) return -1;
89 
90   if (info->sock == CERF_SOCKET)
91     info->irq=IRQ_GPIO_CF_IRQ;
92 
93   return 0;
94 }
95 
cerf_pcmcia_configure_socket(const struct pcmcia_configure * configure)96 static int cerf_pcmcia_configure_socket(const struct pcmcia_configure
97 					   *configure)
98 {
99   if(configure->sock>1)
100     return -1;
101 
102   if (configure->sock != CERF_SOCKET)
103     return 0;
104 
105   switch(configure->vcc){
106   case 0:
107     break;
108 
109   case 50:
110   case 33:
111 #ifdef CONFIG_SA1100_CERF_CPLD
112      GPCR = GPIO_PWR_SHUTDOWN;
113 #endif
114      break;
115 
116   default:
117     printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
118 	   configure->vcc);
119     return -1;
120   }
121 
122   if(configure->reset)
123   {
124 #ifdef CONFIG_SA1100_CERF_CPLD
125     GPSR = GPIO_CF_RESET;
126 #endif
127   }
128   else
129   {
130 #ifdef CONFIG_SA1100_CERF_CPLD
131     GPCR = GPIO_CF_RESET;
132 #endif
133   }
134 
135   return 0;
136 }
137 
cerf_pcmcia_socket_init(int sock)138 static int cerf_pcmcia_socket_init(int sock)
139 {
140   int i;
141 
142   if (sock == CERF_SOCKET)
143     for (i = 0; i < ARRAY_SIZE(irqs); i++)
144       set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_BOTH_EDGES);
145 
146   return 0;
147 }
148 
cerf_pcmcia_socket_suspend(int sock)149 static int cerf_pcmcia_socket_suspend(int sock)
150 {
151   int i;
152 
153   if (sock == CERF_SOCKET)
154     for (i = 0; i < ARRAY_SIZE(irqs); i++)
155       set_GPIO_IRQ_edge(irqs[i].gpio, GPIO_NO_EDGES);
156 
157   return 0;
158 }
159 
160 struct pcmcia_low_level cerf_pcmcia_ops = {
161   init:			cerf_pcmcia_init,
162   shutdown:		cerf_pcmcia_shutdown,
163   socket_state:		cerf_pcmcia_socket_state,
164   get_irq_info:		cerf_pcmcia_get_irq_info,
165   configure_socket:	cerf_pcmcia_configure_socket,
166 
167   socket_init:		cerf_pcmcia_socket_init,
168   socket_suspend:	cerf_pcmcia_socket_suspend,
169 };
170 
171