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
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>
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:
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
63 * EGPIO4_CF_3V3_ON // Output only
67 #define _debug(s, args...) printk (KERN_INFO s, ##args)
68 #define _debug_func(s, args...) _debug ("%s: " s, __FUNCTION__, ##args)
70 #define _debug(s, args...)
71 #define _debug_func(s, args...) _debug ("%s: " s, __FUNCTION__, ##args)
74 static struct pcmcia_irqs hx4700_cd_irq
[] = {
75 { 0, 0, "PCMCIA CD" } /* fill in IRQ below */
78 static int power_en
=0;
81 hx4700_cf_reset( int state
)
83 _debug_func ("%d\n", state
);
84 SET_HX4700_GPIO( CF_RESET
, state
?1:0 );
88 hx4700_pcmcia_hw_init( struct soc_pcmcia_socket
*skt
)
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
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
);
115 hx4700_egpio_enable( EGPIO4_CF_3V3_ON
);
116 set_irq_type( irq
, IRQT_RISING
);
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.
141 hx4700_pcmcia_hw_shutdown( struct soc_pcmcia_socket
*skt
)
144 soc_pcmcia_free_irqs( skt
, hx4700_cd_irq
, ARRAY_SIZE(hx4700_cd_irq
) );
148 hx4700_pcmcia_socket_state( struct soc_pcmcia_socket
*skt
,
149 struct pcmcia_state
*state
)
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;
165 asic3_set_gpio_status_c( &hx4700_asic3
.dev
, 1<<GPIOC_CIOR_N
,
168 asic3_set_gpio_status_c( &hx4700_asic3
.dev
, 1<<GPIOC_CIOR_N
, 0 );
171 _debug( "detect:%d ready:%d vcc:%d\n",
172 state
->detect
, state
->ready
, state
->vs_3v
);
176 hx4700_pcmcia_config_socket( struct soc_pcmcia_socket
*skt
,
177 const socket_state_t
*state
)
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
,
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 */
203 else if (state
->Vcc
== 33 || state
->Vcc
== 50) {
204 hx4700_egpio_enable( EGPIO4_CF_3V3_ON
);
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
219 printk (KERN_ERR
"%s: Unsupported Vcc:%d\n",
220 __FUNCTION__
, state
->Vcc
);
226 * Enable card status IRQs on (re-)initialisation. This can
227 * be called at initialisation, power management event, or
231 hx4700_pcmcia_socket_init(struct soc_pcmcia_socket
*skt
)
237 * Disable card status IRQs on suspend.
240 hx4700_pcmcia_socket_suspend( struct soc_pcmcia_socket
*skt
)
245 static struct pcmcia_low_level hx4700_pcmcia_ops
= {
246 .owner
= THIS_MODULE
,
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",
259 .platform_data
= &hx4700_pcmcia_ops
,
264 hx4700_pcmcia_init(void)
266 if (!machine_is_h4700())
270 return platform_device_register( &hx4700_pcmcia_device
);
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 :*/