patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / drivers / pcmcia / sa1100_flexanet.c
1 /*
2  * drivers/pcmcia/sa1100_flexanet.c
3  *
4  * PCMCIA implementation routines for Flexanet.
5  * by Jordi Colomer, 09/05/2001
6  *
7  */
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/sched.h>
11 #include <linux/device.h>
12 #include <linux/init.h>
13
14 #include <asm/hardware.h>
15 #include <asm/mach-types.h>
16 #include <asm/irq.h>
17 #include "sa1100_generic.h"
18
19 static struct pcmcia_irqs irqs[] = {
20         { 0, IRQ_GPIO_CF1_CD,   "CF1_CD"   },
21         { 0, IRQ_GPIO_CF1_BVD1, "CF1_BVD1" },
22         { 1, IRQ_GPIO_CF2_CD,   "CF2_CD"   },
23         { 1, IRQ_GPIO_CF2_BVD1, "CF2_BVD1" }
24 };
25
26 /*
27  * Socket initialization.
28  *
29  * Called by sa1100_pcmcia_driver_init on startup.
30  */
31 static int flexanet_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
32 {
33         skt->irq = skt->nr ? IRQ_GPIO_CF2_IRQ : IRQ_GPIO_CF1_IRQ;
34
35         return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
36 }
37
38
39 /*
40  * Socket shutdown
41  */
42 static void flexanet_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
43 {
44         soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
45 }
46
47
48 /*
49  * Get the state of the sockets.
50  *
51  *  Sockets in Flexanet are 3.3V only, without BVD2.
52  *
53  */
54 static void
55 flexanet_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
56                              struct pcmcia_state *state)
57 {
58         unsigned long levels = GPLR; /* Sense the GPIOs, asynchronously */
59
60         switch (skt->nr) {
61         ase 0: /* Socket 0 */
62                 state->detect = ((levels & GPIO_CF1_NCD)==0)?1:0;
63                 state->ready  = (levels & GPIO_CF1_IRQ)?1:0;
64                 state->bvd1   = (levels & GPIO_CF1_BVD1)?1:0;
65                 state->bvd2   = 1;
66                 state->wrprot = 0;
67                 state->vs_3v  = 1;
68                 state->vs_Xv  = 0;
69                 break;
70
71         case 1: /* Socket 1 */
72                 state->detect = ((levels & GPIO_CF2_NCD)==0)?1:0;
73                 state->ready  = (levels & GPIO_CF2_IRQ)?1:0;
74                 state->bvd1   = (levels & GPIO_CF2_BVD1)?1:0;
75                 state->bvd2   = 1;
76                 state->wrprot = 0;
77                 state->vs_3v  = 1;
78                 state->vs_Xv  = 0;
79                 break;
80         }
81 }
82
83
84 /*
85  *
86  */
87 static int
88 flexanet_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
89                                  const socket_state_t *state)
90 {
91         unsigned long value, flags, mask;
92
93         /* Ignore the VCC level since it is 3.3V and always on */
94         switch (state->Vcc) {
95         case 0:
96                 printk(KERN_WARNING "%s(): CS asked to power off.\n",
97                         __FUNCTION__);
98                 break;
99
100         case 50:
101                 printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
102                         __FUNCTION__);
103
104         case 33:
105                 break;
106
107         default:
108                 printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
109                        state->Vcc);
110                 return -1;
111         }
112
113         /* Reset the slot(s) using the controls in the BCR */
114         mask = 0;
115
116         switch (skt->nr) {
117         case 0:
118                 mask = FHH_BCR_CF1_RST;
119                 break;
120         case 1:
121                 mask = FHH_BCR_CF2_RST;
122                 break;
123         }
124
125         local_irq_save(flags);
126
127         value = flexanet_BCR;
128         value = (state->flags & SS_RESET) ? (value | mask) : (value & ~mask);
129         FHH_BCR = flexanet_BCR = value;
130
131         local_irq_restore(flags);
132
133         return 0;
134 }
135
136 static void flexanet_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
137 {
138         soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
139 }
140
141 static void flexanet_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
142 {
143         soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
144 }
145
146 /*
147  * The set of socket operations
148  *
149  */
150 static struct pcmcia_low_level flexanet_pcmcia_ops = {
151         .owner                  = THIS_MODULE,
152         .hw_init                = flexanet_pcmcia_hw_init,
153         .hw_shutdown            = flexanet_pcmcia_hw_shutdown,
154         .socket_state           = flexanet_pcmcia_socket_state,
155         .configure_socket       = flexanet_pcmcia_configure_socket,
156         .socket_init            = flexanet_pcmcia_socket_init,
157         .socket_suspend         = flexanet_pcmcia_socket_suspend,
158 };
159
160 int __init pcmcia_flexanet_init(struct device *dev)
161 {
162         int ret = -ENODEV;
163
164         if (machine_is_flexanet())
165                 ret = sa11xx_drv_pcmcia_probe(dev, &flexanet_pcmcia_ops, 0, 2);
166
167         return ret;
168 }