1 /*
2  * linux/drivers/pcmcia/sa1100_sa1111.c
3  *
4  * We implement the generic parts of a SA1111 PCMCIA driver.  This
5  * basically means we handle everything except controlling the
6  * power.  Power is machine specific...
7  */
8 #include <linux/kernel.h>
9 #include <linux/sched.h>
10 #include <linux/ioport.h>
11 
12 #include <asm/hardware.h>
13 #include <asm/hardware/sa1111.h>
14 #include <asm/irq.h>
15 
16 #include "sa1100_generic.h"
17 #include "sa1111_generic.h"
18 
19 static struct irqs {
20 	int irq;
21 	const char *str;
22 } irqs[] = {
23 	{ S0_CD_VALID,    "SA1111 PCMCIA card detect" },
24 	{ S0_BVD1_STSCHG, "SA1111 PCMCIA BVD1"        },
25 	{ S1_CD_VALID,    "SA1111 CF card detect"     },
26 	{ S1_BVD1_STSCHG, "SA1111 CF BVD1"            },
27 };
28 
sa1111_pcmcia_init(struct pcmcia_init * init)29 int sa1111_pcmcia_init(struct pcmcia_init *init)
30 {
31 	int i, ret;
32 
33 	if (!request_mem_region(_PCCR, 512, "PCMCIA"))
34 		return -1;
35 
36 	INTPOL1 |= SA1111_IRQMASK_HI(S0_CD_VALID) |
37 		   SA1111_IRQMASK_HI(S1_CD_VALID) |
38 		   SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
39 		   SA1111_IRQMASK_HI(S1_BVD1_STSCHG);
40 
41 	for (i = ret = 0; i < ARRAY_SIZE(irqs); i++) {
42 		ret = request_irq(irqs[i].irq, init->handler, SA_INTERRUPT,
43 				  irqs[i].str, NULL);
44 		if (ret)
45 			break;
46 	}
47 
48 	if (i < ARRAY_SIZE(irqs)) {
49 		printk(KERN_ERR "sa1111_pcmcia: unable to grab IRQ%d (%d)\n",
50 			irqs[i].irq, ret);
51 		while (i--)
52 			free_irq(irqs[i].irq, NULL);
53 
54 		release_mem_region(_PCCR, 16);
55 	}
56 
57 	return ret ? -1 : 2;
58 }
59 
sa1111_pcmcia_shutdown(void)60 int sa1111_pcmcia_shutdown(void)
61 {
62 	int i;
63 
64 	for (i = 0; i < ARRAY_SIZE(irqs); i++)
65 		free_irq(irqs[i].irq, NULL);
66 
67 	INTPOL1 &= ~(SA1111_IRQMASK_HI(S0_CD_VALID) |
68 		     SA1111_IRQMASK_HI(S1_CD_VALID) |
69 		     SA1111_IRQMASK_HI(S0_BVD1_STSCHG) |
70 		     SA1111_IRQMASK_HI(S1_BVD1_STSCHG));
71 
72 	release_mem_region(_PCCR, 512);
73 
74 	return 0;
75 }
76 
sa1111_pcmcia_socket_state(struct pcmcia_state_array * state)77 int sa1111_pcmcia_socket_state(struct pcmcia_state_array *state)
78 {
79 	unsigned long status;
80 
81 	if (state->size < 2)
82 		return -1;
83 
84 	status = PCSR;
85 
86 	state->state[0].detect = status & PCSR_S0_DETECT ? 0 : 1;
87 	state->state[0].ready  = status & PCSR_S0_READY  ? 1 : 0;
88 	state->state[0].bvd1   = status & PCSR_S0_BVD1   ? 1 : 0;
89 	state->state[0].bvd2   = status & PCSR_S0_BVD2   ? 1 : 0;
90 	state->state[0].wrprot = status & PCSR_S0_WP     ? 1 : 0;
91 	state->state[0].vs_3v  = status & PCSR_S0_VS1    ? 0 : 1;
92 	state->state[0].vs_Xv  = status & PCSR_S0_VS2    ? 0 : 1;
93 
94 	state->state[1].detect = status & PCSR_S1_DETECT ? 0 : 1;
95 	state->state[1].ready  = status & PCSR_S1_READY  ? 1 : 0;
96 	state->state[1].bvd1   = status & PCSR_S1_BVD1   ? 1 : 0;
97 	state->state[1].bvd2   = status & PCSR_S1_BVD2   ? 1 : 0;
98 	state->state[1].wrprot = status & PCSR_S1_WP     ? 1 : 0;
99 	state->state[1].vs_3v  = status & PCSR_S1_VS1    ? 0 : 1;
100 	state->state[1].vs_Xv  = status & PCSR_S1_VS2    ? 0 : 1;
101 
102 	return 1;
103 }
104 
sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info * info)105 int sa1111_pcmcia_get_irq_info(struct pcmcia_irq_info *info)
106 {
107 	int ret = 0;
108 
109 	switch (info->sock) {
110 	case 0:	info->irq = S0_READY_NINT;	break;
111 	case 1: info->irq = S1_READY_NINT;	break;
112 	default: ret = 1;
113 	}
114 
115 	return ret;
116 }
117 
sa1111_pcmcia_configure_socket(const struct pcmcia_configure * conf)118 int sa1111_pcmcia_configure_socket(const struct pcmcia_configure *conf)
119 {
120 	unsigned int rst, flt, wait, pse, irq, pccr_mask;
121 	unsigned long flags;
122 
123 	switch (conf->sock) {
124 	case 0:
125 		rst = PCCR_S0_RST;
126 		flt = PCCR_S0_FLT;
127 		wait = PCCR_S0_PWAITEN;
128 		pse = PCCR_S0_PSE;
129 		irq = S0_READY_NINT;
130 		break;
131 
132 	case 1:
133 		rst = PCCR_S1_RST;
134 		flt = PCCR_S1_FLT;
135 		wait = PCCR_S1_PWAITEN;
136 		pse = PCCR_S1_PSE;
137 		irq = S1_READY_NINT;
138 		break;
139 
140 	default:
141 		return -1;
142 	}
143 
144 	switch (conf->vcc) {
145 	case 0:
146 		pccr_mask = 0;
147 		break;
148 
149 	case 33:
150 		pccr_mask = wait;
151 		break;
152 
153 	case 50:
154 		pccr_mask = pse | wait;
155 		break;
156 
157 	default:
158 		printk(KERN_ERR "sa1111_pcmcia: unrecognised VCC %u\n",
159 			conf->vcc);
160 		return -1;
161 	}
162 
163 	if (conf->reset)
164 		pccr_mask |= rst;
165 
166 	if (conf->output)
167 		pccr_mask |= flt;
168 
169 	local_irq_save(flags);
170 	PCCR = (PCCR & ~(pse | flt | wait | rst)) | pccr_mask;
171 	local_irq_restore(flags);
172 
173 	if (conf->irq)
174 		enable_irq(irq);
175 	else
176 		disable_irq(irq);
177 
178 	return 0;
179 }
180 
sa1111_pcmcia_socket_init(int sock)181 int sa1111_pcmcia_socket_init(int sock)
182 {
183 	return 0;
184 }
185 
sa1111_pcmcia_socket_suspend(int sock)186 int sa1111_pcmcia_socket_suspend(int sock)
187 {
188 	return 0;
189 }
190