hh.org updates
[hh.org.git] / arch / arm / mach-pxa / eseries / e740_pcmcia.c
blob68fe9c469caa0828a89c9b4328a267c55e12fad7
1 /*
2 * arch/arm/mach-pxa/e740_pcmcia.c
4 * Toshiba E-740 PCMCIA specific routines.
6 * Created: 20040704
7 * Author: Ian Molton
8 * Copyright: Ian Molton
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.
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/device.h>
22 #include <pcmcia/ss.h>
23 #include <linux/platform_device.h>
26 #include <asm/hardware.h>
27 #include <asm/irq.h>
29 #include <asm/mach-types.h>
30 #include <asm/arch/pxa-regs.h>
31 #include <asm/arch/eseries-gpio.h>
33 #include "soc_common.h"
35 static struct pcmcia_irqs cd_irqs[] = {
36 { 0, IRQ_GPIO(GPIO_E740_PCMCIA_CD0), "CF card detect" },
37 { 1, IRQ_GPIO(GPIO_E740_PCMCIA_CD1), "Wifi switch" },
40 static int e740_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
42 skt->irq = skt->nr == 0 ? IRQ_GPIO(GPIO_E740_PCMCIA_RDY0):
43 IRQ_GPIO(GPIO_E740_PCMCIA_RDY1);
45 return soc_pcmcia_request_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
49 * Release all resources.
51 static void e740_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
53 soc_pcmcia_free_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
56 #define GPLR_BIT(n) (GPLR((n)) & GPIO_bit((n)))
58 static void e740_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
60 // unsigned long gplr0 = GPLR0; FIXME - this really ought to be atomic
61 // unsigned long gplr1 = GPLR1;
63 if(skt->nr == 0){
64 state->detect = GPLR_BIT(GPIO_E740_PCMCIA_CD0) ? 0 : 1;
65 state->ready = GPLR_BIT(GPIO_E740_PCMCIA_RDY0) ? 1 : 0;
67 else{
68 state->detect = GPLR_BIT(GPIO_E740_PCMCIA_CD1) ? 0 : 1;
69 state->ready = GPLR_BIT(GPIO_E740_PCMCIA_RDY1) ? 1 : 0;
72 state->vs_3v = 1; //FIXME - is it right?
74 state->bvd1 = 1;
75 state->bvd2 = 1;
76 state->wrprot = 0;
77 state->vs_Xv = 0;
80 #define GPSR_BIT(n) (GPSR((n)) = GPIO_bit((n)))
81 #define GPCR_BIT(n) (GPCR((n)) = GPIO_bit((n)))
83 static int e740_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
85 /* reset it? */
86 if(state->flags & SS_RESET) {
87 if(skt->nr == 0)
88 GPSR_BIT(GPIO_E740_PCMCIA_RST0);
89 else
90 GPSR_BIT(GPIO_E740_PCMCIA_RST1);
91 } else {
92 if(skt->nr == 0)
93 GPCR_BIT(GPIO_E740_PCMCIA_RST0);
94 else
95 GPCR_BIT(GPIO_E740_PCMCIA_RST1);
98 /* Apply socket voltage */
99 switch (state->Vcc) {
100 case 0:
101 if(skt->nr == 0)
102 GPCR_BIT(GPIO_E740_PCMCIA_PWR0);
103 else
104 GPSR_BIT(GPIO_E740_PCMCIA_PWR1);
105 break;
106 case 50:
107 case 33:
108 /* Apply power to socket */
109 if(skt->nr == 0)
110 GPSR_BIT(GPIO_E740_PCMCIA_PWR0);
111 else
112 GPCR_BIT(GPIO_E740_PCMCIA_PWR1);
113 break;
114 default:
115 printk (KERN_ERR "%s: Unsupported Vcc:%d\n", __FUNCTION__, state->Vcc);
118 return 0;
122 * Enable card status IRQs on (re-)initialisation. This can
123 * be called at initialisation, power management event, or
124 * pcmcia event.
126 static void e740_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
128 soc_pcmcia_enable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
132 * Disable card status IRQs on suspend.
134 static void e740_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
136 soc_pcmcia_disable_irqs(skt, cd_irqs, ARRAY_SIZE(cd_irqs));
139 static struct pcmcia_low_level e740_pcmcia_ops = {
140 .owner = THIS_MODULE,
141 .hw_init = e740_pcmcia_hw_init,
142 .hw_shutdown = e740_pcmcia_hw_shutdown,
143 .socket_state = e740_pcmcia_socket_state,
144 .configure_socket = e740_pcmcia_configure_socket,
145 .socket_init = e740_pcmcia_socket_init,
146 .socket_suspend = e740_pcmcia_socket_suspend,
147 .nr = 2,
150 static struct platform_device e740_pcmcia_device = {
151 .name = "pxa2xx-pcmcia",
152 .dev = {
153 .platform_data = &e740_pcmcia_ops,
157 static int __init e740_pcmcia_init(void)
159 int ret = 0;
161 if(!machine_is_e740())
162 return -ENODEV;
164 printk("pcmcia: e740 detected.\n");
166 ret = platform_device_register(&e740_pcmcia_device);
168 return ret;
171 static void __exit e740_pcmcia_exit(void)
174 * This call is supposed to free our e740_pcmcia_device.
175 * Unfortunately platform_device don't have a free method, and
176 * we can't assume it's free of any reference at this point so we
177 * can't free it either.
179 //platform_device_unregister(&e740_pcmcia_device);
182 module_init(e740_pcmcia_init);
183 module_exit(e740_pcmcia_exit);
185 MODULE_LICENSE("GPL");