1 /*
2  * drivers/pcmcia/sa1100_xp860.c
3  *
4  * XP860 PCMCIA specific routines
5  *
6  */
7 #include <linux/kernel.h>
8 #include <linux/delay.h>
9 #include <linux/sched.h>
10 
11 #include <asm/hardware.h>
12 #include <asm/irq.h>
13 #include "sa1100_generic.h"
14 
15 #define NCR_A0VPP	(1<<16)
16 #define NCR_A1VPP	(1<<17)
17 
xp860_pcmcia_init(struct pcmcia_init * init)18 static int xp860_pcmcia_init(struct pcmcia_init *init)
19 {
20   /* Set GPIO_A<3:0> to be outputs for PCMCIA/CF power controller: */
21   PA_DDR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
22 
23   /* MAX1600 to standby mode: */
24   PA_DWR &= ~(GPIO_GPIO0 | GPIO_GPIO1 | GPIO_GPIO2 | GPIO_GPIO3);
25 
26 #error Consider the following comment
27   /*
28    * 1- Please move GPDR initialisation  where it is interrupt or preemption
29    *    safe (like from xp860_map_io).
30    * 2- The GPCR line is bogus i.e. it will simply have absolutely no effect.
31    *    Please see its definition in the SA1110 manual.
32    * 3- Please do not use NCR_* values!
33    */
34   GPDR |= (NCR_A0VPP | NCR_A1VPP);
35   GPCR &= ~(NCR_A0VPP | NCR_A1VPP);
36 
37   return sa1111_pcmcia_init(init);
38 }
39 
40 static int
xp860_pcmcia_configure_socket(const struct pcmcia_configure * conf)41 xp860_pcmcia_configure_socket(const struct pcmcia_configure *conf)
42 {
43   unsigned int gpio_mask, pa_dwr_mask;
44   unsigned int gpio_set, pa_dwr_set;
45   int ret;
46 
47   /* Neponset uses the Maxim MAX1600, with the following connections:
48 #warning ^^^ This isn't a neponset!
49    *
50    *   MAX1600      Neponset
51    *
52    *    A0VCC        SA-1111 GPIO A<1>
53    *    A1VCC        SA-1111 GPIO A<0>
54    *    A0VPP        CPLD NCR A0VPP
55    *    A1VPP        CPLD NCR A1VPP
56    *    B0VCC        SA-1111 GPIO A<2>
57    *    B1VCC        SA-1111 GPIO A<3>
58    *    B0VPP        ground (slot B is CF)
59    *    B1VPP        ground (slot B is CF)
60    *
61    *     VX          VCC (5V)
62    *     VY          VCC3_3 (3.3V)
63    *     12INA       12V
64    *     12INB       ground (slot B is CF)
65    *
66    * The MAX1600 CODE pin is tied to ground, placing the device in
67    * "Standard Intel code" mode. Refer to the Maxim data sheet for
68    * the corresponding truth table.
69    */
70 
71   switch (conf->sock) {
72   case 0:
73     pa_dwr_mask = GPIO_GPIO0 | GPIO_GPIO1;
74     gpio_mask = NCR_A0VPP | NCR_A1VPP;
75 
76     switch (conf->vcc) {
77     default:
78     case 0:	pa_dwr_set = 0;			break;
79     case 33:	pa_dwr_set = GPIO_GPIO1;	break;
80     case 50:	pa_dwr_set = GPIO_GPIO0;	break;
81     }
82 
83     switch (conf->vpp) {
84     case 0:	gpio_set = 0;			break;
85     case 120:	gpio_set = NCR_A1VPP;		break;
86 
87     default:
88       if (conf->vpp == conf->vcc)
89 	gpio_set = NCR_A0VPP;
90       else {
91 	printk(KERN_ERR "%s(): unrecognized Vpp %u\n",
92 	       __FUNCTION__, conf->vpp);
93 	return -1;
94       }
95     }
96     break;
97 
98   case 1:
99     pa_dwr_mask = GPIO_GPIO2 | GPIO_GPIO3;
100     gpio_mask = 0;
101     gpio_set = 0;
102 
103     switch (conf->vcc) {
104     default:
105     case 0:	pa_dwr_set = 0;			break;
106     case 33:	pa_dwr_set = GPIO_GPIO2;	break;
107     case 50:	pa_dwr_set = GPIO_GPIO3;	break;
108     }
109 
110     if (conf->vpp != conf->vcc && conf->vpp != 0) {
111       printk(KERN_ERR "%s(): CF slot cannot support Vpp %u\n",
112 	     __FUNCTION__, conf->vpp);
113       return -1;
114     }
115     break;
116   }
117 
118   ret = sa1111_pcmcia_configure_socket(conf);
119   if (ret == 0) {
120     unsigned long flags;
121 
122     local_irq_save(flags);
123     PA_DWR = (PA_DWR & ~pa_dwr_mask) | pa_dwr_set;
124     GPSR = gpio_set;
125     GPCR = gpio_set ^ gpio_mask;
126     local_irq_restore(flags);
127   }
128 
129   return ret;
130 }
131 
132 struct pcmcia_low_level xp860_pcmcia_ops = {
133   init:			xp860_pcmcia_init,
134   shutdown:		sa1111_pcmcia_shutdown,
135   socket_state:		sa1111_pcmcia_socket_state,
136   get_irq_info:		sa1111_pcmcia_get_irq_info,
137   configure_socket:	xp860_pcmcia_configure_socket,
138 
139   socket_init:		sa1111_pcmcia_socket_init,
140   socket_suspend:	sa1111_pcmcia_socket_suspend,
141 };
142 
143