2 * drivers/pcmcia/sa1100_graphicsclient.c
4 * PCMCIA implementation routines for Graphics Client Plus
7 * Turn power OFF at startup
8 * 1/31/2001 Woojung Huh
9 * Fix for GC Plus PCMCIA Reset Problem
10 * 2/27/2001 Woojung Huh [whuh@applieddata.net]
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/sched.h>
17 #include <linux/delay.h>
18 #include <linux/device.h>
19 #include <linux/init.h>
21 #include <asm/hardware.h>
22 #include <asm/mach-types.h>
24 #include "sa1100_generic.h"
26 #error This is broken!
28 #define S0_CD_IRQ 60 // Socket 0 Card Detect IRQ
29 #define S0_STS_IRQ 55 // Socket 0 PCMCIA IRQ
31 static volatile unsigned long *PCMCIA_Status
=
32 ((volatile unsigned long *) ADS_p2v(_ADS_CS_STATUS
));
34 static volatile unsigned long *PCMCIA_Power
=
35 ((volatile unsigned long *) ADS_p2v(_ADS_CS_PR
));
37 static struct pcmcia_irqs irqs
[] = {
38 { 0, S0_CD_IRQ
, "PCMCIA 0 CD" },
41 static int gcplus_pcmcia_init(struct soc_pcmcia_socket
*skt
)
44 // Reset Timing for CPLD(U2) version 8001E or later
45 *PCMCIA_Power
&= ~ ADS_CS_PR_A_RESET
;
46 udelay(12); // 12 uSec
48 *PCMCIA_Power
|= ADS_CS_PR_A_RESET
;
49 mdelay(30); // 30 mSec
52 *PCMCIA_Power
&= ~0x03;
54 skt
->irq
= S0_STS_IRQ
;
56 /* Register interrupts */
57 return soc_pcmcia_request_irqs(skt
, irqs
, ARRAY_SIZE(irqs
));
60 static void gcplus_pcmcia_hw_shutdown(struct soc_pcmcia_socket
*skt
)
63 free_irq(S0_CD_IRQ
, skt
);
65 /* Shutdown PCMCIA power */
67 *PCMCIA_Power
&= ~0x03;
71 gcplus_pcmcia_socket_state(struct soc_pcmcia_socket
*skt
, struct pcmcia_state
*state
)
73 unsigned long levels
= *PCMCIA_Status
;
75 state
->detect
=(levels
& ADS_CS_ST_A_CD
)?1:0;
76 state
->ready
=(levels
& ADS_CS_ST_A_READY
)?1:0;
85 gcplus_pcmcia_configure_socket(struct soc_pcmcia_socket
*skt
,
86 const socket_state_t
*state
)
90 local_irq_save(flags
);
94 *PCMCIA_Power
&= ~(ADS_CS_PR_A_3V_POWER
| ADS_CS_PR_A_5V_POWER
);
98 *PCMCIA_Power
&= ~(ADS_CS_PR_A_3V_POWER
| ADS_CS_PR_A_5V_POWER
);
99 *PCMCIA_Power
|= ADS_CS_PR_A_5V_POWER
;
103 *PCMCIA_Power
&= ~(ADS_CS_PR_A_3V_POWER
| ADS_CS_PR_A_5V_POWER
);
104 *PCMCIA_Power
|= ADS_CS_PR_A_3V_POWER
;
108 printk(KERN_ERR
"%s(): unrecognized Vcc %u\n",
109 __FUNCTION__
, state
->Vcc
);
110 local_irq_restore(flags
);
114 /* Silently ignore Vpp, output enable, speaker enable. */
117 *PCMCIA_Power
&= ~ ADS_CS_PR_A_RESET
;
120 *PCMCIA_Power
|= ADS_CS_PR_A_RESET
;
123 local_irq_restore(flags
);
128 static void gcplus_pcmcia_socket_init(struct soc_pcmcia_socket
*skt
)
132 static void gcplus_pcmcia_socket_suspend(struct soc_pcmcia_socket
*skt
)
136 static struct pcmcia_low_level gcplus_pcmcia_ops
= {
137 .owner
= THIS_MODULE
,
138 .hw_init
= gcplus_pcmcia_hw_init
,
139 .hw_shutdown
= gcplus_pcmcia_hw_shutdown
,
140 .socket_state
= gcplus_pcmcia_socket_state
,
141 .configure_socket
= gcplus_pcmcia_configure_socket
,
142 .socket_init
= gcplus_pcmcia_socket_init
,
143 .socket_suspend
= gcplus_pcmcia_socket_suspend
,
146 int __init
pcmcia_gcplus_init(struct device
*dev
)
150 if (machine_is_gcplus())
151 ret
= sa11xx_drv_pcmcia_probe(dev
, &gcplus_pcmcia_ops
, 0, 1);