MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / pcmcia / sa1100_graphicsclient.c
blob08b5a9dffcf9a3f7de30cb83a6a88ba5a28db1b2
1 /*
2 * drivers/pcmcia/sa1100_graphicsclient.c
4 * PCMCIA implementation routines for Graphics Client Plus
6 * 9/12/01 Woojung
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]
11 * Fix
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>
23 #include <asm/irq.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)
43 // Reset PCMCIA
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
51 // Turn off 5V
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)
62 /* disable IRQs */
63 free_irq(S0_CD_IRQ, skt);
65 /* Shutdown PCMCIA power */
66 mdelay(2); // 2msec
67 *PCMCIA_Power &= ~0x03;
70 static void
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;
77 state->bvd1= 0;
78 state->bvd2= 0;
79 state->wrprot=0;
80 state->vs_3v=0;
81 state->vs_Xv=0;
84 static int
85 gcplus_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
86 const socket_state_t *state)
88 unsigned long flags;
90 local_irq_save(flags);
92 switch (state->Vcc) {
93 case 0:
94 *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
95 break;
97 case 50:
98 *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
99 *PCMCIA_Power |= ADS_CS_PR_A_5V_POWER;
100 break;
102 case 33:
103 *PCMCIA_Power &= ~(ADS_CS_PR_A_3V_POWER | ADS_CS_PR_A_5V_POWER);
104 *PCMCIA_Power |= ADS_CS_PR_A_3V_POWER;
105 break;
107 default:
108 printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
109 __FUNCTION__, state->Vcc);
110 local_irq_restore(flags);
111 return -1;
114 /* Silently ignore Vpp, output enable, speaker enable. */
116 // Reset PCMCIA
117 *PCMCIA_Power &= ~ ADS_CS_PR_A_RESET;
118 udelay(12);
120 *PCMCIA_Power |= ADS_CS_PR_A_RESET;
121 mdelay(30);
123 local_irq_restore(flags);
125 return 0;
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)
148 int ret = -ENODEV;
150 if (machine_is_gcplus())
151 ret = sa11xx_drv_pcmcia_probe(dev, &gcplus_pcmcia_ops, 0, 1);
153 return ret;