sync hh.org
[hh.org.git] / arch / arm / mach-pxa / hx4700 / hx4700_pcmcia.c
blob7ded0e4d004f066018ca44a3452e6ff63f1c4dde
1 /*
2 * iPAQ hx4700 PCMCIA support
4 * Copyright (c) 2005 SDG Systems, LLC
6 * Based on code from iPAQ h2200
7 * Copyright (c) 2004 Koen Kooi <koen@handhelds.org>
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file COPYING in the main directory of this archive for
11 * more details.
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/errno.h>
17 #include <linux/interrupt.h>
18 #include <linux/irq.h>
19 #include <linux/init.h>
20 #include <linux/platform_device.h>
21 #include <linux/delay.h>
22 #include <linux/soc-old.h>
24 #include <asm/mach-types.h>
25 #include <asm/hardware.h>
26 #include <asm/irq.h>
28 #include <asm/arch/pxa-regs.h>
29 #include <asm/arch/hx4700-gpio.h>
30 #include <asm/arch/hx4700-asic.h>
31 #include <asm/arch/hx4700-core.h>
32 #include <asm/hardware/ipaq-asic3.h>
33 #include <linux/soc/asic3_base.h>
35 #include "../../../../drivers/pcmcia/soc_common.h"
37 extern struct platform_device hx4700_asic3;
40 * CF resources used on the HX4700:
41 * from hx4700-asic.h
42 * GPIOC_CF_CD_N 4 // Input
43 * GPIOC_CIOW_N 5 // Output, to CF socket
44 * GPIOC_CIOR_N 6 // Output, to CF socket
45 * GPIOC_CF_PWE_N 10 // Input
46 * GPIOD_CF_CD_N 4 // Input, from CF socket
47 * GPIOD_CIOIS16_N 11 // Input, from CF socket
48 * GPIOD_CWAIT_N 12 // Input, from CF socket
49 * GPIOD_CF_RNB 13 // Input (read, not busy?)
50 * from hx4700-gpio.h / hx4700.c
51 * pxa_gpio_mode(GPIO_NR_HX4700_POE_N_MD);
52 * pxa_gpio_mode(GPIO_NR_HX4700_PWE_N_MD);
53 * pxa_gpio_mode(GPIO_NR_HX4700_PIOR_N_MD);
54 * pxa_gpio_mode(GPIO_NR_HX4700_PIOW_N_MD);
55 * pxa_gpio_mode(GPIO_NR_HX4700_PCE1_N_MD);
56 * pxa_gpio_mode(GPIO_NR_HX4700_PCE2_N_MD);
57 * pxa_gpio_mode(GPIO_NR_HX4700_PREG_N_MD);
58 * pxa_gpio_mode(GPIO_NR_HX4700_PWAIT_N_MD);
59 * pxa_gpio_mode(GPIO_NR_HX4700_PIOIS16_N_MD);
60 * GPIO_NR_HX4700_CF_RNB 60 // Input
61 * GPIO_NR_HX4700_CF_RESET 114 // Output
62 * EGPIOs
63 * EGPIO4_CF_3V3_ON // Output only
66 #if 0
67 #define _debug(s, args...) printk (KERN_INFO s, ##args)
68 #define _debug_func(s, args...) _debug ("%s: " s, __FUNCTION__, ##args)
69 #else
70 #define _debug(s, args...)
71 #define _debug_func(s, args...) _debug ("%s: " s, __FUNCTION__, ##args)
72 #endif
74 static struct pcmcia_irqs hx4700_cd_irq[] = {
75 { 0, 0, "PCMCIA CD" } /* fill in IRQ below */
78 static int power_en=0;
80 static void
81 hx4700_cf_reset( int state )
83 _debug_func ("%d\n", state);
84 SET_HX4700_GPIO( CF_RESET, state?1:0 );
87 static int
88 hx4700_pcmcia_hw_init( struct soc_pcmcia_socket *skt )
90 int statusd;
91 int irq;
93 _debug_func ("\n");
95 /* Turn on sleep mode, I think */
96 asic3_set_extcf_select(&hx4700_asic3.dev,
97 ASIC3_EXTCF_CF0_SLEEP_MODE | ASIC3_EXTCF_CF1_SLEEP_MODE |
98 ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF1_BUF_EN |
99 ASIC3_EXTCF_CF0_PWAIT_EN | ASIC3_EXTCF_CF1_PWAIT_EN,
101 ASIC3_EXTCF_CF0_SLEEP_MODE | ASIC3_EXTCF_CF1_SLEEP_MODE |
102 ASIC3_EXTCF_CF0_BUF_EN | 0 |
103 ASIC3_EXTCF_CF0_PWAIT_EN | 0
105 mdelay(50);
107 statusd = asic3_get_gpio_status_d( &hx4700_asic3.dev );
108 power_en = (statusd & (1<<GPIOD_CF_CD_N)) ? 0 : 1;
110 irq = hx4700_cd_irq[0].irq = asic3_irq_base( &hx4700_asic3.dev )
111 + ASIC3_GPIOD_IRQ_BASE + GPIOD_CF_CD_N;
112 skt->irq = HX4700_IRQ( CF_RNB );
114 if (power_en) {
115 hx4700_egpio_enable( EGPIO4_CF_3V3_ON );
116 set_irq_type( irq, IRQT_RISING );
118 else {
119 hx4700_egpio_disable( EGPIO4_CF_3V3_ON );
120 set_irq_type( irq, IRQT_FALLING );
123 pxa_gpio_mode(GPIO_NR_HX4700_POE_N_MD | GPIO_DFLT_HIGH);
124 pxa_gpio_mode(GPIO_NR_HX4700_PWE_N_MD | GPIO_DFLT_HIGH);
125 pxa_gpio_mode(GPIO_NR_HX4700_PIOR_N_MD | GPIO_DFLT_HIGH);
126 pxa_gpio_mode(GPIO_NR_HX4700_PIOW_N_MD | GPIO_DFLT_HIGH);
127 pxa_gpio_mode(GPIO_NR_HX4700_PCE1_N_MD | GPIO_DFLT_HIGH);
128 pxa_gpio_mode(GPIO_NR_HX4700_PCE2_N_MD | GPIO_DFLT_HIGH);
129 pxa_gpio_mode(GPIO_NR_HX4700_PREG_N_MD | GPIO_DFLT_HIGH);
130 pxa_gpio_mode(GPIO_NR_HX4700_PWAIT_N_MD | GPIO_DFLT_HIGH);
131 pxa_gpio_mode(GPIO_NR_HX4700_PIOIS16_N_MD | GPIO_DFLT_HIGH);
132 pxa_gpio_mode(GPIO_NR_HX4700_PSKTSEL_MD);
134 return soc_pcmcia_request_irqs(skt, hx4700_cd_irq, ARRAY_SIZE(hx4700_cd_irq));
138 * Release all resources.
140 static void
141 hx4700_pcmcia_hw_shutdown( struct soc_pcmcia_socket *skt )
143 _debug_func ("\n");
144 soc_pcmcia_free_irqs( skt, hx4700_cd_irq, ARRAY_SIZE(hx4700_cd_irq) );
147 static void
148 hx4700_pcmcia_socket_state( struct soc_pcmcia_socket *skt,
149 struct pcmcia_state *state )
151 int statusd;
153 statusd = asic3_get_gpio_status_d( &hx4700_asic3.dev );
154 // printk( "hx4700_pcmcia_socket_state: statusd=0x%x\n", statusd );
155 state->detect = (statusd & (1<<GPIOD_CF_CD_N)) ? 0 : 1;
156 state->ready = GET_HX4700_GPIO( CF_RNB ) ? 1 : 0;
157 state->bvd1 = 1;
158 state->bvd2 = 1;
159 state->wrprot = 0;
160 state->vs_3v = 1;
161 state->vs_Xv = 0;
163 #if 0
164 if (state->detect)
165 asic3_set_gpio_status_c( &hx4700_asic3.dev, 1<<GPIOC_CIOR_N,
166 1<<GPIOC_CIOR_N );
167 else
168 asic3_set_gpio_status_c( &hx4700_asic3.dev, 1<<GPIOC_CIOR_N, 0 );
169 #endif
171 _debug( "detect:%d ready:%d vcc:%d\n",
172 state->detect, state->ready, state->vs_3v );
175 static int
176 hx4700_pcmcia_config_socket( struct soc_pcmcia_socket *skt,
177 const socket_state_t *state )
179 int statusc;
181 statusc = asic3_get_gpio_status_c( &hx4700_asic3.dev );
182 /* Silently ignore Vpp, output enable, speaker enable. */
183 _debug_func( "Reset:%d Vcc:%d Astatusc=0x%x\n",
184 (state->flags & SS_RESET) ? 1 : 0, state->Vcc,
185 statusc );
187 hx4700_cf_reset( state->flags & SS_RESET );
188 if (state->Vcc == 0) {
189 /* Turn on sleep mode, I think. No docs for these bits. */
190 asic3_set_extcf_select(&hx4700_asic3.dev,
191 ASIC3_EXTCF_CF0_SLEEP_MODE | ASIC3_EXTCF_CF1_SLEEP_MODE |
192 ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF1_BUF_EN |
193 ASIC3_EXTCF_CF0_PWAIT_EN | ASIC3_EXTCF_CF1_PWAIT_EN,
195 ASIC3_EXTCF_CF0_SLEEP_MODE | ASIC3_EXTCF_CF1_SLEEP_MODE |
196 ASIC3_EXTCF_CF0_BUF_EN | 0 |
197 ASIC3_EXTCF_CF0_PWAIT_EN | 0
199 hx4700_egpio_disable( EGPIO4_CF_3V3_ON );
200 hx4700_cf_reset(1); /* Ensure the slot is reset when powered off */
201 power_en = 0;
203 else if (state->Vcc == 33 || state->Vcc == 50) {
204 hx4700_egpio_enable( EGPIO4_CF_3V3_ON );
205 mdelay(1);
206 /* Turn on CF stuff without messing with SD bit 14. */
207 asic3_set_extcf_select(&hx4700_asic3.dev,
208 ASIC3_EXTCF_CF0_SLEEP_MODE | ASIC3_EXTCF_CF1_SLEEP_MODE |
209 ASIC3_EXTCF_CF0_BUF_EN | ASIC3_EXTCF_CF1_BUF_EN |
210 ASIC3_EXTCF_CF0_PWAIT_EN | ASIC3_EXTCF_CF1_PWAIT_EN,
212 0 | ASIC3_EXTCF_CF1_SLEEP_MODE |
213 ASIC3_EXTCF_CF0_BUF_EN | 0 |
214 ASIC3_EXTCF_CF0_PWAIT_EN | 0
216 power_en = 1;
218 else {
219 printk (KERN_ERR "%s: Unsupported Vcc:%d\n",
220 __FUNCTION__, state->Vcc);
222 return 0;
226 * Enable card status IRQs on (re-)initialisation. This can
227 * be called at initialisation, power management event, or
228 * pcmcia event.
230 static void
231 hx4700_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
233 _debug_func ("\n");
237 * Disable card status IRQs on suspend.
239 static void
240 hx4700_pcmcia_socket_suspend( struct soc_pcmcia_socket *skt )
242 _debug_func ("\n");
245 static struct pcmcia_low_level hx4700_pcmcia_ops = {
246 .owner = THIS_MODULE,
247 .nr = 1,
248 .hw_init = hx4700_pcmcia_hw_init,
249 .hw_shutdown = hx4700_pcmcia_hw_shutdown,
250 .socket_state = hx4700_pcmcia_socket_state,
251 .configure_socket = hx4700_pcmcia_config_socket,
252 .socket_init = hx4700_pcmcia_socket_init,
253 .socket_suspend = hx4700_pcmcia_socket_suspend,
256 static struct platform_device hx4700_pcmcia_device = {
257 .name = "pxa2xx-pcmcia",
258 .dev = {
259 .platform_data = &hx4700_pcmcia_ops,
263 static int __init
264 hx4700_pcmcia_init(void)
266 if (!machine_is_h4700())
267 return -ENODEV;
268 _debug_func ("\n");
270 return platform_device_register( &hx4700_pcmcia_device );
273 static void __exit
274 hx4700_pcmcia_exit(void)
276 platform_device_unregister( &hx4700_pcmcia_device );
279 module_init(hx4700_pcmcia_init);
280 module_exit(hx4700_pcmcia_exit);
282 MODULE_AUTHOR("Todd Blumer, SDG Systems, LLC");
283 MODULE_DESCRIPTION("iPAQ Hx4700 PCMCIA/CF platform-specific driver");
284 MODULE_LICENSE("GPL");
286 /* vim600: set noexpandtab sw=8 ts=8 :*/