Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  *
  3  * Alchemy Semi Db1x00 boards specific pcmcia routines.
  4  *
  5  * Copyright 2002 MontaVista Software Inc.
  6  * Author: MontaVista Software, Inc.
  7  *              ppopov@mvista.com or source@mvista.com
  8  *
  9  * Copyright 2004 Pete Popov, updated the driver to 2.6.
 10  * Followed the sa11xx API and largely copied many of the hardware
 11  * independent functions.
 12  *
 13  * ########################################################################
 14  *
 15  *  This program is free software; you can distribute it and/or modify it
 16  *  under the terms of the GNU General Public License (Version 2) as
 17  *  published by the Free Software Foundation.
 18  *
 19  *  This program is distributed in the hope it will be useful, but WITHOUT
 20  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 21  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 22  *  for more details.
 23  *
 24  *  You should have received a copy of the GNU General Public License along
 25  *  with this program; if not, write to the Free Software Foundation, Inc.,
 26  *  59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
 27  *
 28  * ########################################################################
 29  *
 30  *
 31  */
 32 
 33 #include <linux/module.h>
 34 #include <linux/kernel.h>
 35 #include <linux/errno.h>
 36 #include <linux/interrupt.h>
 37 #include <linux/device.h>
 38 #include <linux/init.h>
 39 
 40 #include <asm/irq.h>
 41 #include <asm/signal.h>
 42 #include <asm/mach-au1x00/au1000.h>
 43 #include <asm/mach-db1x00/db1x00.h>
 44 
 45 #include "au1000_generic.h"
 46 
 47 #if 0
 48 #define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args)
 49 #else
 50 #define debug(x,args...)
 51 #endif
 52 
 53 static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
 54 
 55 struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS];
 56 extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int);
 57 
 58 static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt)
 59 {
 60 #ifdef CONFIG_MIPS_DB1550
 61         skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3;
 62 #else
 63         skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2;
 64 #endif
 65         return 0;
 66 }
 67 
 68 static void db1x00_pcmcia_shutdown(struct au1000_pcmcia_socket *skt)
 69 {
 70         bcsr->pcmcia = 0; /* turn off power */
 71         au_sync_delay(2);
 72 }
 73 
 74 static void
 75 db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state *state)
 76 {
 77         u32 inserted;
 78         unsigned char vs;
 79 
 80         state->ready = 0;
 81         state->vs_Xv = 0;
 82         state->vs_3v = 0;
 83         state->detect = 0;
 84 
 85         switch (skt->nr) {
 86         case 0:
 87                 vs = bcsr->status & 0x3;
 88                 inserted = !(bcsr->status & (1<<4));
 89                 break;
 90         case 1:
 91                 vs = (bcsr->status & 0xC)>>2;
 92                 inserted = !(bcsr->status & (1<<5));
 93                 break;
 94         default:/* should never happen */
 95                 return;
 96         }
 97 
 98         if (inserted)
 99                 debug("db1x00 socket %d: inserted %d, vs %d pcmcia %x\n",
100                                 skt->nr, inserted, vs, bcsr->pcmcia);
101 
102         if (inserted) {
103                 switch (vs) {
104                         case 0:
105                         case 2:
106                                 state->vs_3v=1;
107                                 break;
108                         case 3: /* 5V */
109                                 break;
110                         default:
111                                 /* return without setting 'detect' */
112                                 printk(KERN_ERR "db1x00 bad VS (%d)\n",
113                                                 vs);
114                 }
115                 state->detect = 1;
116                 state->ready = 1;
117         }
118         else {
119                 /* if the card was previously inserted and then ejected,
120                  * we should turn off power to it
121                  */
122                 if ((skt->nr == 0) && (bcsr->pcmcia & BCSR_PCMCIA_PC0RST)) {
123                         bcsr->pcmcia &= ~(BCSR_PCMCIA_PC0RST |
124                                         BCSR_PCMCIA_PC0DRVEN |
125                                         BCSR_PCMCIA_PC0VPP |
126                                         BCSR_PCMCIA_PC0VCC);
127                         au_sync_delay(10);
128                 }
129                 else if ((skt->nr == 1) && bcsr->pcmcia & BCSR_PCMCIA_PC1RST) {
130                         bcsr->pcmcia &= ~(BCSR_PCMCIA_PC1RST |
131                                         BCSR_PCMCIA_PC1DRVEN |
132                                         BCSR_PCMCIA_PC1VPP |
133                                         BCSR_PCMCIA_PC1VCC);
134                         au_sync_delay(10);
135                 }
136         }
137 
138         state->bvd1=1;
139         state->bvd2=1;
140         state->wrprot=0;
141 }
142 
143 static int
144 db1x00_pcmcia_configure_socket(struct au1000_pcmcia_socket *skt, struct socket_state_t *state)
145 {
146         u16 pwr;
147         int sock = skt->nr;
148 
149         debug("config_skt %d Vcc %dV Vpp %dV, reset %d\n",
150                         sock, state->Vcc, state->Vpp,
151                         state->flags & SS_RESET);
152 
153         /* pcmcia reg was set to zero at init time. Be careful when
154          * initializing a socket not to wipe out the settings of the
155          * other socket.
156          */
157         pwr = bcsr->pcmcia;
158         pwr &= ~(0xf << sock*8); /* clear voltage settings */
159 
160         state->Vpp = 0;
161         switch(state->Vcc){
162                 case 0:  /* Vcc 0 */
163                         pwr |= SET_VCC_VPP(0,0,sock);
164                         break;
165                 case 50: /* Vcc 5V */
166                         switch(state->Vpp) {
167                                 case 0:
168                                         pwr |= SET_VCC_VPP(2,0,sock);
169                                         break;
170                                 case 50:
171                                         pwr |= SET_VCC_VPP(2,1,sock);
172                                         break;
173                                 case 12:
174                                         pwr |= SET_VCC_VPP(2,2,sock);
175                                         break;
176                                 case 33:
177                                 default:
178                                         pwr |= SET_VCC_VPP(0,0,sock);
179                                         printk("%s: bad Vcc/Vpp (%d:%d)\n",
180                                                         __FUNCTION__,
181                                                         state->Vcc,
182                                                         state->Vpp);
183                                         break;
184                         }
185                         break;
186                 case 33: /* Vcc 3.3V */
187                         switch(state->Vpp) {
188                                 case 0:
189                                         pwr |= SET_VCC_VPP(1,0,sock);
190                                         break;
191                                 case 12:
192                                         pwr |= SET_VCC_VPP(1,2,sock);
193                                         break;
194                                 case 33:
195                                         pwr |= SET_VCC_VPP(1,1,sock);
196                                         break;
197                                 case 50:
198                                 default:
199                                         pwr |= SET_VCC_VPP(0,0,sock);
200                                         printk("%s: bad Vcc/Vpp (%d:%d)\n",
201                                                         __FUNCTION__,
202                                                         state->Vcc,
203                                                         state->Vpp);
204                                         break;
205                         }
206                         break;
207                 default: /* what's this ? */
208                         pwr |= SET_VCC_VPP(0,0,sock);
209                         printk(KERN_ERR "%s: bad Vcc %d\n",
210                                         __FUNCTION__, state->Vcc);
211                         break;
212         }
213 
214         bcsr->pcmcia = pwr;
215         au_sync_delay(300);
216 
217         if (sock == 0) {
218                 if (!(state->flags & SS_RESET)) {
219                         pwr |= BCSR_PCMCIA_PC0DRVEN;
220                         bcsr->pcmcia = pwr;
221                         au_sync_delay(300);
222                         pwr |= BCSR_PCMCIA_PC0RST;
223                         bcsr->pcmcia = pwr;
224                         au_sync_delay(100);
225                 }
226                 else {
227                         pwr &= ~(BCSR_PCMCIA_PC0RST | BCSR_PCMCIA_PC0DRVEN);
228                         bcsr->pcmcia = pwr;
229                         au_sync_delay(100);
230                 }
231         }
232         else {
233                 if (!(state->flags & SS_RESET)) {
234                         pwr |= BCSR_PCMCIA_PC1DRVEN;
235                         bcsr->pcmcia = pwr;
236                         au_sync_delay(300);
237                         pwr |= BCSR_PCMCIA_PC1RST;
238                         bcsr->pcmcia = pwr;
239                         au_sync_delay(100);
240                 }
241                 else {
242                         pwr &= ~(BCSR_PCMCIA_PC1RST | BCSR_PCMCIA_PC1DRVEN);
243                         bcsr->pcmcia = pwr;
244                         au_sync_delay(100);
245                 }
246         }
247         return 0;
248 }
249 
250 /*
251  * Enable card status IRQs on (re-)initialisation.  This can
252  * be called at initialisation, power management event, or
253  * pcmcia event.
254  */
255 void db1x00_socket_init(struct au1000_pcmcia_socket *skt)
256 {
257         /* nothing to do for now */
258 }
259 
260 /*
261  * Disable card status IRQs and PCMCIA bus on suspend.
262  */
263 void db1x00_socket_suspend(struct au1000_pcmcia_socket *skt)
264 {
265         /* nothing to do for now */
266 }
267 
268 struct pcmcia_low_level db1x00_pcmcia_ops = {
269         .owner                  = THIS_MODULE,
270 
271         .hw_init                = db1x00_pcmcia_hw_init,
272         .hw_shutdown            = db1x00_pcmcia_shutdown,
273 
274         .socket_state           = db1x00_pcmcia_socket_state,
275         .configure_socket       = db1x00_pcmcia_configure_socket,
276 
277         .socket_init            = db1x00_socket_init,
278         .socket_suspend         = db1x00_socket_suspend
279 };
280 
281 int __init au1x_board_init(struct device *dev)
282 {
283         int ret = -ENODEV;
284         bcsr->pcmcia = 0; /* turn off power, if it's not already off */
285         au_sync_delay(2);
286         ret = au1x00_pcmcia_socket_probe(dev, &db1x00_pcmcia_ops, 0, 2);
287         return ret;
288 }
289 
  This page was automatically generated by the LXR engine.