initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / pcmcia / sa1100_flexanet.c
blobe48ef99970c950272b4af103495be8070b342843
1 /*
2 * drivers/pcmcia/sa1100_flexanet.c
4 * PCMCIA implementation routines for Flexanet.
5 * by Jordi Colomer, 09/05/2001
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>
14 #include <asm/hardware.h>
15 #include <asm/mach-types.h>
16 #include <asm/irq.h>
17 #include "sa1100_generic.h"
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" }
27 * Socket initialization.
29 * Called by sa1100_pcmcia_driver_init on startup.
31 static int flexanet_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
33 skt->irq = skt->nr ? IRQ_GPIO_CF2_IRQ : IRQ_GPIO_CF1_IRQ;
35 return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
40 * Socket shutdown
42 static void flexanet_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
44 soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
49 * Get the state of the sockets.
51 * Sockets in Flexanet are 3.3V only, without BVD2.
54 static void
55 flexanet_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
56 struct pcmcia_state *state)
58 unsigned long levels = GPLR; /* Sense the GPIOs, asynchronously */
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;
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;
87 static int
88 flexanet_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
89 const socket_state_t *state)
91 unsigned long value, flags, mask;
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;
100 case 50:
101 printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
102 __FUNCTION__);
104 case 33:
105 break;
107 default:
108 printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
109 state->Vcc);
110 return -1;
113 /* Reset the slot(s) using the controls in the BCR */
114 mask = 0;
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;
125 local_irq_save(flags);
127 value = flexanet_BCR;
128 value = (state->flags & SS_RESET) ? (value | mask) : (value & ~mask);
129 FHH_BCR = flexanet_BCR = value;
131 local_irq_restore(flags);
133 return 0;
136 static void flexanet_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
138 soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs));
141 static void flexanet_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
143 soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
147 * The set of socket operations
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,
160 int __init pcmcia_flexanet_init(struct device *dev)
162 int ret = -ENODEV;
164 if (machine_is_flexanet())
165 ret = sa11xx_drv_pcmcia_probe(dev, &flexanet_pcmcia_ops, 0, 2);
167 return ret;