Merge master.kernel.org:/home/rmk/linux-2.6-arm
[linux-2.6] / drivers / pcmcia / pxa2xx_mainstone.c
1 /*
2  * linux/drivers/pcmcia/pxa2xx_mainstone.c
3  *
4  * Mainstone PCMCIA specific routines.
5  *
6  * Created:     May 12, 2004
7  * Author:      Nicolas Pitre
8  * Copyright:   MontaVista Software Inc.
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2 as
12  * published by the Free Software Foundation.
13  */
14
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/kernel.h>
18 #include <linux/errno.h>
19 #include <linux/interrupt.h>
20 #include <linux/platform_device.h>
21
22 #include <pcmcia/ss.h>
23
24 #include <asm/hardware.h>
25 #include <asm/irq.h>
26
27 #include <asm/arch/pxa-regs.h>
28 #include <asm/arch/mainstone.h>
29
30 #include "soc_common.h"
31
32
33 static struct pcmcia_irqs irqs[] = {
34         { 0, MAINSTONE_S0_CD_IRQ, "PCMCIA0 CD" },
35         { 1, MAINSTONE_S1_CD_IRQ, "PCMCIA1 CD" },
36         { 0, MAINSTONE_S0_STSCHG_IRQ, "PCMCIA0 STSCHG" },
37         { 1, MAINSTONE_S1_STSCHG_IRQ, "PCMCIA1 STSCHG" },
38 };
39
40 static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
41 {
42         /*
43          * Setup default state of GPIO outputs
44          * before we enable them as outputs.
45          */
46         GPSR(GPIO48_nPOE) =
47                 GPIO_bit(GPIO48_nPOE) |
48                 GPIO_bit(GPIO49_nPWE) |
49                 GPIO_bit(GPIO50_nPIOR) |
50                 GPIO_bit(GPIO51_nPIOW) |
51                 GPIO_bit(GPIO85_nPCE_1) |
52                 GPIO_bit(GPIO54_nPCE_2);
53
54         pxa_gpio_mode(GPIO48_nPOE_MD);
55         pxa_gpio_mode(GPIO49_nPWE_MD);
56         pxa_gpio_mode(GPIO50_nPIOR_MD);
57         pxa_gpio_mode(GPIO51_nPIOW_MD);
58         pxa_gpio_mode(GPIO85_nPCE_1_MD);
59         pxa_gpio_mode(GPIO54_nPCE_2_MD);
60         pxa_gpio_mode(GPIO79_pSKTSEL_MD);
61         pxa_gpio_mode(GPIO55_nPREG_MD);
62         pxa_gpio_mode(GPIO56_nPWAIT_MD);
63         pxa_gpio_mode(GPIO57_nIOIS16_MD);
64
65         skt->irq = (skt->nr == 0) ? MAINSTONE_S0_IRQ : MAINSTONE_S1_IRQ;
66         return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
67 }
68
69 static void mst_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
70 {
71         soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
72 }
73
74 static unsigned long mst_pcmcia_status[2];
75
76 static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
77                                     struct pcmcia_state *state)
78 {
79         unsigned long status, flip;
80
81         status = (skt->nr == 0) ? MST_PCMCIA0 : MST_PCMCIA1;
82         flip = (status ^ mst_pcmcia_status[skt->nr]) & MST_PCMCIA_nSTSCHG_BVD1;
83
84         /*
85          * Workaround for STSCHG which can't be deasserted:
86          * We therefore disable/enable corresponding IRQs
87          * as needed to avoid IRQ locks.
88          */
89         if (flip) {
90                 mst_pcmcia_status[skt->nr] = status;
91                 if (status & MST_PCMCIA_nSTSCHG_BVD1)
92                         enable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
93                                                    : MAINSTONE_S1_STSCHG_IRQ );
94                 else
95                         disable_irq( (skt->nr == 0) ? MAINSTONE_S0_STSCHG_IRQ
96                                                     : MAINSTONE_S1_STSCHG_IRQ );
97         }
98
99         state->detect = (status & MST_PCMCIA_nCD) ? 0 : 1;
100         state->ready  = (status & MST_PCMCIA_nIRQ) ? 1 : 0;
101         state->bvd1   = (status & MST_PCMCIA_nSTSCHG_BVD1) ? 1 : 0;
102         state->bvd2   = (status & MST_PCMCIA_nSPKR_BVD2) ? 1 : 0;
103         state->vs_3v  = (status & MST_PCMCIA_nVS1) ? 0 : 1;
104         state->vs_Xv  = (status & MST_PCMCIA_nVS2) ? 0 : 1;
105         state->wrprot = 0;  /* not available */
106 }
107
108 static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
109                                        const socket_state_t *state)
110 {
111         unsigned long power = 0;
112         int ret = 0;
113
114         switch (state->Vcc) {
115         case 0:  power |= MST_PCMCIA_PWR_VCC_0;  break;
116         case 33: power |= MST_PCMCIA_PWR_VCC_33; break;
117         case 50: power |= MST_PCMCIA_PWR_VCC_50; break;
118         default:
119                  printk(KERN_ERR "%s(): bad Vcc %u\n",
120                                  __FUNCTION__, state->Vcc);
121                  ret = -1;
122         }
123
124         switch (state->Vpp) {
125         case 0:   power |= MST_PCMCIA_PWR_VPP_0;   break;
126         case 120: power |= MST_PCMCIA_PWR_VPP_120; break;
127         default:
128                   if(state->Vpp == state->Vcc) {
129                           power |= MST_PCMCIA_PWR_VPP_VCC;
130                   } else {
131                           printk(KERN_ERR "%s(): bad Vpp %u\n",
132                                           __FUNCTION__, state->Vpp);
133                           ret = -1;
134                   }
135         }
136
137         if (state->flags & SS_RESET)
138                power |= MST_PCMCIA_RESET;
139
140         switch (skt->nr) {
141         case 0:  MST_PCMCIA0 = power; break;
142         case 1:  MST_PCMCIA1 = power; break;
143         default: ret = -1;
144         }
145
146         return ret;
147 }
148
149 static void mst_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
150 {
151 }
152
153 static void mst_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
154 {
155 }
156
157 static struct pcmcia_low_level mst_pcmcia_ops = {
158         .owner                  = THIS_MODULE,
159         .hw_init                = mst_pcmcia_hw_init,
160         .hw_shutdown            = mst_pcmcia_hw_shutdown,
161         .socket_state           = mst_pcmcia_socket_state,
162         .configure_socket       = mst_pcmcia_configure_socket,
163         .socket_init            = mst_pcmcia_socket_init,
164         .socket_suspend         = mst_pcmcia_socket_suspend,
165         .nr                     = 2,
166 };
167
168 static struct platform_device *mst_pcmcia_device;
169
170 static int __init mst_pcmcia_init(void)
171 {
172         int ret;
173
174         mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
175         if (!mst_pcmcia_device)
176                 return -ENOMEM;
177
178         mst_pcmcia_device->dev.platform_data = &mst_pcmcia_ops;
179
180         ret = platform_device_add(mst_pcmcia_device);
181
182         if (ret)
183                 platform_device_put(mst_pcmcia_device);
184
185         return ret;
186 }
187
188 static void __exit mst_pcmcia_exit(void)
189 {
190         platform_device_unregister(mst_pcmcia_device);
191 }
192
193 fs_initcall(mst_pcmcia_init);
194 module_exit(mst_pcmcia_exit);
195
196 MODULE_LICENSE("GPL");