Blame view

drivers/pcmcia/sa1111_lubbock.c 5.01 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  /*
   * linux/drivers/pcmcia/pxa2xx_lubbock.c
   *
   * Author:	George Davis
   * Created:	Jan 10, 2002
   * Copyright:	MontaVista Software Inc.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   *
   * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c
   *
   * Lubbock PCMCIA specific routines.
   *
   */
  #include <linux/module.h>
  #include <linux/kernel.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
19
20
21
22
  #include <linux/device.h>
  #include <linux/errno.h>
  #include <linux/init.h>
  #include <linux/delay.h>
a09e64fbc   Russell King   [ARM] Move includ...
23
  #include <mach/hardware.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
  #include <asm/hardware/sa1111.h>
  #include <asm/mach-types.h>
a09e64fbc   Russell King   [ARM] Move includ...
26
  #include <mach/lubbock.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
27
28
29
30
  
  #include "sa1111_generic.h"
  
  static int
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31
32
33
  lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  				const socket_state_t *state)
  {
701a5dc05   Russell King - ARM Linux   PCMCIA: sa1111: w...
34
  	struct sa1111_pcmcia_socket *s = to_skt(skt);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
  	unsigned int pa_dwr_mask, pa_dwr_set, misc_mask, misc_set;
  	int ret = 0;
  
  	pa_dwr_mask = pa_dwr_set = misc_mask = misc_set = 0;
  
  	/* Lubbock uses the Maxim MAX1602, with the following connections:
  	 *
  	 * Socket 0 (PCMCIA):
  	 *	MAX1602	Lubbock		Register
  	 *	Pin	Signal
  	 *	-----	-------		----------------------
  	 *	A0VPP	S0_PWR0		SA-1111 GPIO A<0>
  	 *	A1VPP	S0_PWR1		SA-1111 GPIO A<1>
  	 *	A0VCC	S0_PWR2		SA-1111 GPIO A<2>
  	 *	A1VCC	S0_PWR3		SA-1111 GPIO A<3>
  	 *	VX	VCC
  	 *	VY	+3.3V
  	 *	12IN	+12V
  	 *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
  	 *
  	 * Socket 1 (CF):
  	 *	MAX1602	Lubbock		Register
  	 *	Pin	Signal
  	 *	-----	-------		----------------------
  	 *	A0VPP	GND		VPP is not connected
  	 *	A1VPP	GND		VPP is not connected
  	 *	A0VCC	S1_PWR0		MISC_WR<14>
  	 *	A1VCC	S1_PWR1		MISC_WR<15>
  	 *	VX	VCC
  	 *	VY	+3.3V
  	 *	12IN	GND		VPP is not connected
  	 *	CODE	+3.3V		Cirrus  Code, CODE = High (VY)
  	 *
  	 */
  
   again:
  	switch (skt->nr) {
  	case 0:
  		pa_dwr_mask = GPIO_A0 | GPIO_A1 | GPIO_A2 | GPIO_A3;
  
  		switch (state->Vcc) {
  		case 0: /* Hi-Z */
  			break;
  
  		case 33: /* VY */
  			pa_dwr_set |= GPIO_A3;
  			break;
  
  		case 50: /* VX */
  			pa_dwr_set |= GPIO_A2;
  			break;
  
  		default:
  			printk(KERN_ERR "%s(): unrecognized Vcc %u
  ",
2e11cb4c5   Harvey Harrison   pcmcia: replace r...
90
  			       __func__, state->Vcc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  			ret = -1;
  		}
  
  		switch (state->Vpp) {
  		case 0: /* Hi-Z */
  			break;
  
  		case 120: /* 12IN */
  			pa_dwr_set |= GPIO_A1;
  			break;
  
  		default: /* VCC */
  			if (state->Vpp == state->Vcc)
  				pa_dwr_set |= GPIO_A0;
  			else {
  				printk(KERN_ERR "%s(): unrecognized Vpp %u
  ",
2e11cb4c5   Harvey Harrison   pcmcia: replace r...
108
  				       __func__, state->Vpp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
  				ret = -1;
  				break;
  			}
  		}
  		break;
  
  	case 1:
  		misc_mask = (1 << 15) | (1 << 14);
  
  		switch (state->Vcc) {
  		case 0: /* Hi-Z */
  			break;
  
  		case 33: /* VY */
  			misc_set |= 1 << 15;
  			break;
  
  		case 50: /* VX */
  			misc_set |= 1 << 14;
  			break;
  
  		default:
  			printk(KERN_ERR "%s(): unrecognized Vcc %u
  ",
2e11cb4c5   Harvey Harrison   pcmcia: replace r...
133
  			       __func__, state->Vcc);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
135
136
137
138
139
140
  			ret = -1;
  			break;
  		}
  
  		if (state->Vpp != state->Vcc && state->Vpp != 0) {
  			printk(KERN_ERR "%s(): CF slot cannot support Vpp %u
  ",
2e11cb4c5   Harvey Harrison   pcmcia: replace r...
141
  			       __func__, state->Vpp);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
142
143
144
145
146
147
148
149
150
151
152
153
154
155
  			ret = -1;
  			break;
  		}
  		break;
  
  	default:
  		ret = -1;
  	}
  
  	if (ret == 0)
  		ret = sa1111_pcmcia_configure_socket(skt, state);
  
  	if (ret == 0) {
  		lubbock_set_misc_wr(misc_mask, misc_set);
701a5dc05   Russell King - ARM Linux   PCMCIA: sa1111: w...
156
  		sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  	}
  
  #if 1
  	if (ret == 0 && state->Vcc == 33) {
  		struct pcmcia_state new_state;
  
  		/*
  		 * HACK ALERT:
  		 * We can't sense the voltage properly on Lubbock before
  		 * actually applying some power to the socket (catch 22).
  		 * Resense the socket Voltage Sense pins after applying
  		 * socket power.
  		 *
  		 * Note: It takes about 2.5ms for the MAX1602 VCC output
  		 * to rise.
  		 */
  		mdelay(3);
  
  		sa1111_pcmcia_socket_state(skt, &new_state);
  
  		if (!new_state.vs_3v && !new_state.vs_Xv) {
  			/*
  			 * Switch to 5V,  Configure socket with 5V voltage
  			 */
  			lubbock_set_misc_wr(misc_mask, 0);
701a5dc05   Russell King - ARM Linux   PCMCIA: sa1111: w...
182
  			sa1111_set_io(s->dev, pa_dwr_mask, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
184
185
186
187
188
189
190
191
192
  
  			/*
  			 * It takes about 100ms to turn off Vcc.
  			 */
  			mdelay(100);
  
  			/*
  			 * We need to hack around the const qualifier as
  			 * well to keep this ugly workaround localized and
  			 * not force it to the rest of the code. Barf bags
25985edce   Lucas De Marchi   Fix common misspe...
193
  			 * available in the seat pocket in front of you!
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
194
195
196
197
198
199
200
201
202
203
204
205
206
  			 */
  			((socket_state_t *)state)->Vcc = 50;
  			((socket_state_t *)state)->Vpp = 50;
  			goto again;
  		}
  	}
  #endif
  
  	return ret;
  }
  
  static struct pcmcia_low_level lubbock_pcmcia_ops = {
  	.owner			= THIS_MODULE,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
207
  	.configure_socket	= lubbock_pcmcia_configure_socket,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
209
210
211
212
  	.first			= 0,
  	.nr			= 2,
  };
  
  #include "pxa2xx_base.h"
7bbaac12a   David Brownell   pcmcia: remove px...
213
  int pcmcia_lubbock_init(struct sa1111_dev *sadev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214
  {
3f8df892b   Russell King   pcmcia: sa1111: f...
215
216
217
218
219
220
221
  	/*
  	 * Set GPIO_A<3:0> to be outputs for the MAX1600,
  	 * and switch to standby mode.
  	 */
  	sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
  	sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
  	sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
222

3f8df892b   Russell King   pcmcia: sa1111: f...
223
224
  	/* Set CF Socket 1 power to standby mode. */
  	lubbock_set_misc_wr((1 << 15) | (1 << 14), 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225

3f8df892b   Russell King   pcmcia: sa1111: f...
226
  	pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops);
817ed5748   Robert Jarzmik   pcmcia: lubbock: ...
227
  	pxa2xx_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops);
3f8df892b   Russell King   pcmcia: sa1111: f...
228
229
  	return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops,
  				 pxa2xx_drv_pcmcia_add_one);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
230
231
232
  }
  
  MODULE_LICENSE("GPL");