2 * Dell Axim X5 PCMCIA support
4 * Copyright © 2004 Andrew Zabolotny <zap@homelink.ru>
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file COPYING in the main directory of this archive for
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/errno.h>
14 #include <linux/interrupt.h>
15 #include <linux/init.h>
16 #include <linux/device.h>
17 #include <linux/delay.h>
18 #include <linux/soc-old.h>
19 #include <linux/platform_device.h>
21 #include <asm/mach-types.h>
22 #include <asm/hardware.h>
23 #include <../drivers/pcmcia/soc_common.h>
24 #include <asm/arch/pxa-regs.h>
25 #include <asm/arch/aximx5-gpio.h>
28 #include "../drivers/soc/mq11xx.h"
31 # define debug_out(s, args...) printk (KERN_INFO s, ##args)
33 # define debug_out(s, args...)
35 #define debug_func(s, args...) debug_out ("%s: " s, __FUNCTION__, ##args)
37 /* PCMCIA interrupt number, multiplexed off the MediaQ chip */
38 #define IRQ_PCMCIA (mq_base->irq_base + IRQ_MQ_GPIO_2)
40 static struct mediaq11xx_base
*mq_base
;
42 static struct pcmcia_irqs aximx5_cd_irqs
[] = {
43 { 0, AXIMX5_IRQ (PCMCIA_DETECT_N
), "PCMCIA CD" }
46 static void aximx5_cf_rst (int state
)
48 debug_func ("%d\n", state
);
50 SET_AXIMX5_GPIO (PCMCIA_RESET
, state
);
53 static int aximx5_pcmcia_hw_init (struct soc_pcmcia_socket
*skt
)
57 skt
->irq
= IRQ_PCMCIA
;
59 /* GPIOs are configured in machine initialization code */
61 return soc_pcmcia_request_irqs(skt
, aximx5_cd_irqs
,
62 ARRAY_SIZE(aximx5_cd_irqs
));
66 * Release all resources.
68 static void aximx5_pcmcia_hw_shutdown (struct soc_pcmcia_socket
*skt
)
71 soc_pcmcia_free_irqs(skt
, aximx5_cd_irqs
, ARRAY_SIZE(aximx5_cd_irqs
));
75 aximx5_pcmcia_socket_state (struct soc_pcmcia_socket
*skt
, struct pcmcia_state
*state
)
77 state
->detect
= GET_AXIMX5_GPIO (PCMCIA_DETECT_N
) ? 0 : 1;
78 state
->ready
= mq_base
->get_GPIO (mq_base
, 2) ? 1 : 0;
79 state
->bvd1
= GET_AXIMX5_GPIO (PCMCIA_BVD1
) ? 1 : 0;
80 state
->bvd2
= GET_AXIMX5_GPIO (PCMCIA_BVD2
) ? 1 : 0;
82 state
->vs_3v
= mq_base
->get_GPIO (mq_base
, 65) ? 1 : 0;
85 debug_out ("detect:%d ready:%d vcc:%d bvd1:%d bvd2:%d\n",
86 state
->detect
, state
->ready
, state
->vs_3v
, state
->bvd1
, state
->bvd2
);
90 aximx5_pcmcia_configure_socket (struct soc_pcmcia_socket
*skt
, const socket_state_t
*state
)
92 /* Don't enable MediaQ power more than once as it keeps a on/off
93 * counter and this can prevent from powering the device off when
94 * it is no longer in use.
96 static int mq_power_state
= 0;
98 /* Silently ignore Vpp, output enable, speaker enable. */
99 debug_func ("Reset:%d Vcc:%d\n", (state
->flags
& SS_RESET
) ? 1 : 0,
102 aximx5_cf_rst (state
->flags
& SS_RESET
);
104 /* Apply socket voltage */
105 switch (state
->Vcc
) {
107 mq_base
->set_GPIO (mq_base
, 65, MQ_GPIO_IN
| MQ_GPIO_OUT0
);
108 /* Power off the SPI subdevice */
109 if (mq_power_state
) {
110 mq_base
->set_power (mq_base
, MEDIAQ_11XX_SPI_DEVICE_ID
, 0);
113 /* Disable PCMCIA address bus and buffer */
114 SET_AXIMX5_GPIO_N (PCMCIA_BUFF_EN
, 0);
115 SET_AXIMX5_GPIO_N (PCMCIA_ADD_EN
, 0);
119 /* Power on the SPI subdevice as it is responsible for mqGPIO65 */
120 if (!mq_power_state
) {
121 mq_base
->set_power (mq_base
, MEDIAQ_11XX_SPI_DEVICE_ID
, 1);
124 /* Enable PCMCIA address bus and buffer */
125 SET_AXIMX5_GPIO_N (PCMCIA_BUFF_EN
, 1);
126 SET_AXIMX5_GPIO_N (PCMCIA_ADD_EN
, 1);
127 /* Apply power to socket */
128 mq_base
->set_GPIO (mq_base
, 65, MQ_GPIO_IN
| MQ_GPIO_OUT1
);
131 printk (KERN_ERR
"%s: Unsupported Vcc:%d\n",
132 __FUNCTION__
, state
->Vcc
);
139 * Enable card status IRQs on (re-)initialisation. This can
140 * be called at initialisation, power management event, or
143 static void aximx5_pcmcia_socket_init(struct soc_pcmcia_socket
*skt
)
146 soc_pcmcia_enable_irqs (skt
, aximx5_cd_irqs
, ARRAY_SIZE(aximx5_cd_irqs
));
150 * Disable card status IRQs on suspend.
152 static void aximx5_pcmcia_socket_suspend (struct soc_pcmcia_socket
*skt
)
156 soc_pcmcia_disable_irqs(skt
, aximx5_cd_irqs
, ARRAY_SIZE(aximx5_cd_irqs
));
159 static struct pcmcia_low_level aximx5_pcmcia_ops
= {
160 .owner
= THIS_MODULE
,
165 .hw_init
= aximx5_pcmcia_hw_init
,
166 .hw_shutdown
= aximx5_pcmcia_hw_shutdown
,
168 .socket_state
= aximx5_pcmcia_socket_state
,
169 .configure_socket
= aximx5_pcmcia_configure_socket
,
171 .socket_init
= aximx5_pcmcia_socket_init
,
172 .socket_suspend
= aximx5_pcmcia_socket_suspend
,
175 static void aximx5_pcmcia_release (struct device
* dev
)
177 /* No need to free the structure since it is a static variable */
180 static struct platform_device aximx5_pcmcia_device
= {
181 .name
= "pxa2xx-pcmcia",
184 .platform_data
= &aximx5_pcmcia_ops
,
185 .release
= aximx5_pcmcia_release
190 aximx5_pcmcia_init(void)
194 if(!machine_is_aximx5())
197 if (mq_driver_get ()) {
198 debug_out ("MediaQ base driver not found\n");
202 if (mq_device_enum (&mq_base
, 1) <= 0) {
204 debug_out ("MediaQ 1132 chip not found\n");
208 return platform_device_register (&aximx5_pcmcia_device
);
212 aximx5_pcmcia_exit(void)
214 platform_device_unregister (&aximx5_pcmcia_device
);
218 module_init(aximx5_pcmcia_init
);
219 module_exit(aximx5_pcmcia_exit
);
221 MODULE_AUTHOR("Andrew Zabolotny <zap@homelink.ru>");
222 MODULE_DESCRIPTION("Dell Axim X5 PCMCIA platform-specific driver");
223 MODULE_LICENSE("GPL");