1 /*
2  * drivers/pcmcia/sa1100_pangolin.c
3  *
4  * PCMCIA implementation routines for Pangolin
5  *
6  */
7 #include <linux/kernel.h>
8 #include <linux/sched.h>
9 
10 #include <asm/hardware.h>
11 #include <asm/irq.h>
12 #include "sa1100_generic.h"
13 
pangolin_pcmcia_init(struct pcmcia_init * init)14 static int pangolin_pcmcia_init(struct pcmcia_init *init){
15   int irq, res;
16 
17 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
18   /* Enable PCMCIA bus: */
19   GPCR = GPIO_PCMCIA_BUS_ON;
20 #endif
21 
22   /* Set transition detect */
23   set_GPIO_IRQ_edge( GPIO_PCMCIA_CD, GPIO_BOTH_EDGES );
24   set_GPIO_IRQ_edge( GPIO_PCMCIA_IRQ, GPIO_FALLING_EDGE );
25 
26   /* Register interrupts */
27   irq = IRQ_PCMCIA_CD;
28   res = request_irq( irq, init->handler, SA_INTERRUPT, "PCMCIA_CD", NULL );
29   if( res < 0 ) goto irq_err;
30 
31   /* There's only one slot, but it's "Slot 1": */
32   return 2;
33 
34 irq_err:
35   printk( KERN_ERR "%s: Request for IRQ %lu failed\n", __FUNCTION__, irq );
36   return -1;
37 }
38 
pangolin_pcmcia_shutdown(void)39 static int pangolin_pcmcia_shutdown(void)
40 {
41   /* disable IRQs */
42   free_irq( IRQ_PCMCIA_CD, NULL );
43 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
44     /* Disable PCMCIA bus: */
45     GPSR = GPIO_PCMCIA_BUS_ON;
46 #endif
47   return 0;
48 }
49 
pangolin_pcmcia_socket_state(struct pcmcia_state_array * state_array)50 static int pangolin_pcmcia_socket_state(struct pcmcia_state_array
51 				       *state_array){
52   unsigned long levels;
53 
54   if(state_array->size<2) return -1;
55 
56   memset(state_array->state, 0,
57 	 (state_array->size)*sizeof(struct pcmcia_state));
58 
59   levels=GPLR;
60 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
61   state_array->state[1].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
62   state_array->state[1].ready=(levels & GPIO_PCMCIA_IRQ)?1:0;
63   state_array->state[1].bvd1=1; /* Not available on Pangolin. */
64   state_array->state[1].bvd2=1; /* Not available on Pangolin. */
65   state_array->state[1].wrprot=0; /* Not available on Pangolin. */
66   state_array->state[1].vs_3v=1;  /* Can only apply 3.3V on Pangolin. */
67   state_array->state[1].vs_Xv=0;
68 #else
69   state_array->state[0].detect=((levels & GPIO_PCMCIA_CD)==0)?1:0;
70   state_array->state[0].ready=(levels & GPIO_PCMCIA_IRQ)?1:0;
71   state_array->state[0].bvd1=1; /* Not available on Pangolin. */
72   state_array->state[0].bvd2=1; /* Not available on Pangolin. */
73   state_array->state[0].wrprot=0; /* Not available on Pangolin. */
74   state_array->state[0].vs_3v=0;  /* voltage level is determined by jumper setting */
75   state_array->state[0].vs_Xv=0;
76 #endif
77   return 1;
78 }
79 
pangolin_pcmcia_get_irq_info(struct pcmcia_irq_info * info)80 static int pangolin_pcmcia_get_irq_info(struct pcmcia_irq_info *info){
81 
82   if(info->sock>1) return -1;
83 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
84   if(info->sock==1)
85 	info->irq=IRQ_PCMCIA_IRQ;
86 #else
87   if(info->sock==0)
88         info->irq=IRQ_PCMCIA_IRQ;
89 #endif
90   return 0;
91 }
92 
pangolin_pcmcia_configure_socket(const struct pcmcia_configure * configure)93 static int pangolin_pcmcia_configure_socket(const struct pcmcia_configure
94 					   *configure)
95 {
96   unsigned long value, flags;
97 
98   if(configure->sock>1) return -1;
99 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
100   if(configure->sock==0) return 0;
101 #endif
102   save_flags_cli(flags);
103 
104   /* Murphy: BUS_ON different from POWER ? */
105 
106   switch(configure->vcc){
107   case 0:
108     break;
109 #ifndef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
110   case 50:
111     printk(KERN_WARNING "%s(): CS asked for 5V, applying 3.3V...\n",
112 	   __FUNCTION__);
113   case 33:  /* Can only apply 3.3V to the CF slot. */
114     break;
115 #else
116   case 50:
117     printk(KERN_WARNING "%s(): CS asked for 5V, determinded by jumper setting...\n", __FUNCTION__);
118     break;
119   case 33:
120     printk(KERN_WARNING "%s(): CS asked for 3.3V, determined by jumper setting...\n", __FUNCTION__);
121     break;
122 #endif
123   default:
124     printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
125 	   configure->vcc);
126     restore_flags(flags);
127     return -1;
128   }
129 #ifdef CONFIG_SA1100_PANGOLIN_PCMCIA_IDE
130   /* reset & unreset request */
131   if(configure->sock==0) {
132 	if(configure->reset) {
133 		GPSR |= GPIO_PCMCIA_RESET;
134 	} else {
135 		GPCR |= GPIO_PCMCIA_RESET;
136 	}
137   }
138 #endif
139   /* Silently ignore Vpp, output enable, speaker enable. */
140   restore_flags(flags);
141   return 0;
142 }
143 
pangolin_pcmcia_socket_init(int sock)144 static int pangolin_pcmcia_socket_init(int sock)
145 {
146   /* enable card status IRQs - see sa1100_assabet.c for details  */
147   return -1;
148 }
149 
pangolin_pcmcia_socket_suspend(int sock)150 static int pangolin_pcmcia_socket_suspend(int sock)
151 {
152   /* disable card status IRQs - see sa1100_assabet.c for details */
153   return -1;
154 }
155 
156 struct pcmcia_low_level pangolin_pcmcia_ops = {
157   init:			pangolin_pcmcia_init,
158   shutdown:		pangolin_pcmcia_shutdown,
159   socket_state:		pangolin_pcmcia_socket_state,
160   get_irq_info:		pangolin_pcmcia_get_irq_info,
161   configure_socket:	pangolin_pcmcia_configure_socket,
162 
163   socket_init:		pangolin_pcmcia_socket_init,
164   socket_suspend,	pangolin_pcmcia_socket_suspend,
165 };
166 
167