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