patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / pcmcia / sa1100_stork.c
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 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/kernel.h>
24 #include <linux/sched.h>
25 #include <linux/device.h>
26
27 #include <asm/hardware.h>
28 #include <asm/mach-types.h>
29 #include <asm/irq.h>
30 #include "sa1100_generic.h"
31
32 static int debug = 0;
33
34 static struct pcmcia_irqs irqs[] = {
35         { 0, IRQ_GPIO_STORK_PCMCIA_A_CARD_DETECT, "PCMCIA_CD0" },
36         { 1, IRQ_GPIO_STORK_PCMCIA_B_CARD_DETECT, "PCMCIA_CD1" },
37 };
38
39 static int stork_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
40 {
41         printk("in stork_pcmcia_init\n");
42
43         skt->irq = skt->nr ? IRQ_GPIO_STORK_PCMCIA_B_RDY
44                            : IRQ_GPIO_STORK_PCMCIA_A_RDY;
45
46         return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
47 }
48
49 static void stork_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
50 {
51         int i;
52
53         printk("%s\n", __FUNCTION__);
54
55         /* disable IRQs */
56         soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
57   
58         /* Disable CF bus: */
59         storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
60         storkClearLatchA(STORK_PCMCIA_A_POWER_ON);
61         storkClearLatchA(STORK_PCMCIA_B_POWER_ON);
62 }
63
64 static void
65 stork_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
66                           struct pcmcia_state *state)
67 {
68         unsigned long levels = GPLR;
69
70         if (debug > 1)
71                 printk("%s GPLR=%x IRQ[1:0]=%x\n", __FUNCTION__, levels,
72                         (levels & (GPIO_STORK_PCMCIA_A_RDY|GPIO_STORK_PCMCIA_B_RDY)));
73
74         switch (skt->nr) {
75         case 0:
76                 state->detect=((levels & GPIO_STORK_PCMCIA_A_CARD_DETECT)==0)?1:0;
77                 state->ready=(levels & GPIO_STORK_PCMCIA_A_RDY)?1:0;
78                 state->bvd1= 1;
79                 state->bvd2= 1;
80                 state->wrprot=0;
81                 state->vs_3v=1;
82                 state->vs_Xv=0;
83                 break;
84
85         case 1:
86                 state->detect=((levels & GPIO_STORK_PCMCIA_B_CARD_DETECT)==0)?1:0;
87                 state->ready=(levels & GPIO_STORK_PCMCIA_B_RDY)?1:0;
88                 state->bvd1=1;
89                 state->bvd2=1;
90                 state->wrprot=0;
91                 state->vs_3v=1;
92                 state->vs_Xv=0;
93                 break;
94         }
95 }
96
97 static int
98 stork_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
99                               const socket_state_t *state)
100 {
101         unsigned long flags;
102         int DETECT, RDY, POWER, RESET;
103
104         printk("%s: socket=%d vcc=%d vpp=%d reset=%d\n", __FUNCTION__,
105                 skt->nr, state->Vcc, state->Vpp, state->flags & SS_RESET ? 1 : 0);
106
107         local_irq_save(flags);
108
109         if (skt->nr == 0) {
110             DETECT = GPIO_STORK_PCMCIA_A_CARD_DETECT;
111             RDY = GPIO_STORK_PCMCIA_A_RDY;
112             POWER = STORK_PCMCIA_A_POWER_ON;
113             RESET = STORK_PCMCIA_A_RESET;
114         } else {
115             DETECT = GPIO_STORK_PCMCIA_B_CARD_DETECT;
116             RDY = GPIO_STORK_PCMCIA_B_RDY;
117             POWER = STORK_PCMCIA_B_POWER_ON;
118             RESET = STORK_PCMCIA_B_RESET;
119         }
120     
121 /*
122         if (storkTestGPIO(DETECT)) {
123            printk("no card detected - but resetting anyway\r\n");
124         }
125 */
126         switch (state->Vcc) {
127         case 0:
128 /*              storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON); */
129                 storkClearLatchA(POWER);
130                 break;
131
132         case 50:
133         case 33:
134                 storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
135                 storkSetLatchA(POWER);
136                 break;
137
138         default:
139                 printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
140                        state->Vcc);
141                 local_irq_restore(flags);
142                 return -1;
143         }
144
145         if (state->flags & SS_RESET)
146                 storkSetLatchB(RESET);
147         else
148                 storkClearLatchB(RESET);
149
150         local_irq_restore(flags);
151
152         /* silently ignore vpp and speaker enables. */
153
154         printk("%s: finished\n", __FUNCTION__);
155
156         return 0;
157 }
158
159 static void stork_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
160 {
161         storkSetLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
162
163         soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
164 }
165
166 static void stork_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
167 {
168         soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
169
170         /*
171          * Hack!
172          */
173         if (skt->nr == 1)
174                 storkClearLatchA(STORK_PCMCIA_PULL_UPS_POWER_ON);
175
176         return 0;
177 }
178
179 static struct pcmcia_low_level stork_pcmcia_ops = { 
180         .owner                  = THIS_MODULE,
181         .hw_init                = stork_pcmcia_hw_init,
182         .hw_shutdown            = stork_pcmcia_hw_shutdown,
183         .socket_state           = stork_pcmcia_socket_state,
184         .configure_socket       = stork_pcmcia_configure_socket,
185
186         .socket_init            = stork_pcmcia_socket_init,
187         .socket_suspend         = stork_pcmcia_socket_suspend,
188 };
189
190 int __init pcmcia_stork_init(struct device *dev)
191 {
192         int ret = -ENODEV;
193
194         if (machine_is_stork())
195                 ret = sa11xx_drv_pcmcia_probe(dev, &stork_pcmcia_ops, 0, 2);
196
197         return ret;
198 }