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