Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32 305 lines 7.3 kB view raw
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 44#if defined(CONFIG_MIPS_DB1200) 45 #include <db1200.h> 46#elif defined(CONFIG_MIPS_PB1200) 47 #include <pb1200.h> 48#else 49 #include <asm/mach-db1x00/db1x00.h> 50 static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; 51#endif 52 53#include "au1000_generic.h" 54 55#if 0 56#define debug(x,args...) printk(KERN_DEBUG "%s: " x, __func__ , ##args) 57#else 58#define debug(x,args...) 59#endif 60 61 62struct au1000_pcmcia_socket au1000_pcmcia_socket[PCMCIA_NUM_SOCKS]; 63extern int au1x00_pcmcia_socket_probe(struct device *, struct pcmcia_low_level *, int, int); 64 65static int db1x00_pcmcia_hw_init(struct au1000_pcmcia_socket *skt) 66{ 67#ifdef CONFIG_MIPS_DB1550 68 skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_3; 69#elif defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) 70 skt->irq = skt->nr ? BOARD_PC1_INT : BOARD_PC0_INT; 71#else 72 skt->irq = skt->nr ? AU1000_GPIO_5 : AU1000_GPIO_2; 73#endif 74 return 0; 75} 76 77static void db1x00_pcmcia_shutdown(struct au1000_pcmcia_socket *skt) 78{ 79 bcsr->pcmcia = 0; /* turn off power */ 80 au_sync_delay(2); 81} 82 83static void 84db1x00_pcmcia_socket_state(struct au1000_pcmcia_socket *skt, struct pcmcia_state *state) 85{ 86 u32 inserted; 87 unsigned char vs; 88 89 state->ready = 0; 90 state->vs_Xv = 0; 91 state->vs_3v = 0; 92 state->detect = 0; 93 94 switch (skt->nr) { 95 case 0: 96 vs = bcsr->status & 0x3; 97#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) 98 inserted = BOARD_CARD_INSERTED(0); 99#else 100 inserted = !(bcsr->status & (1<<4)); 101#endif 102 break; 103 case 1: 104 vs = (bcsr->status & 0xC)>>2; 105#if defined(CONFIG_MIPS_DB1200) || defined(CONFIG_MIPS_PB1200) 106 inserted = BOARD_CARD_INSERTED(1); 107#else 108 inserted = !(bcsr->status & (1<<5)); 109#endif 110 break; 111 default:/* should never happen */ 112 return; 113 } 114 115 if (inserted) 116 debug("db1x00 socket %d: inserted %d, vs %d pcmcia %x\n", 117 skt->nr, inserted, vs, bcsr->pcmcia); 118 119 if (inserted) { 120 switch (vs) { 121 case 0: 122 case 2: 123 state->vs_3v=1; 124 break; 125 case 3: /* 5V */ 126 break; 127 default: 128 /* return without setting 'detect' */ 129 printk(KERN_ERR "db1x00 bad VS (%d)\n", 130 vs); 131 } 132 state->detect = 1; 133 state->ready = 1; 134 } 135 else { 136 /* if the card was previously inserted and then ejected, 137 * we should turn off power to it 138 */ 139 if ((skt->nr == 0) && (bcsr->pcmcia & BCSR_PCMCIA_PC0RST)) { 140 bcsr->pcmcia &= ~(BCSR_PCMCIA_PC0RST | 141 BCSR_PCMCIA_PC0DRVEN | 142 BCSR_PCMCIA_PC0VPP | 143 BCSR_PCMCIA_PC0VCC); 144 au_sync_delay(10); 145 } 146 else if ((skt->nr == 1) && bcsr->pcmcia & BCSR_PCMCIA_PC1RST) { 147 bcsr->pcmcia &= ~(BCSR_PCMCIA_PC1RST | 148 BCSR_PCMCIA_PC1DRVEN | 149 BCSR_PCMCIA_PC1VPP | 150 BCSR_PCMCIA_PC1VCC); 151 au_sync_delay(10); 152 } 153 } 154 155 state->bvd1=1; 156 state->bvd2=1; 157 state->wrprot=0; 158} 159 160static int 161db1x00_pcmcia_configure_socket(struct au1000_pcmcia_socket *skt, struct socket_state_t *state) 162{ 163 u16 pwr; 164 int sock = skt->nr; 165 166 debug("config_skt %d Vcc %dV Vpp %dV, reset %d\n", 167 sock, state->Vcc, state->Vpp, 168 state->flags & SS_RESET); 169 170 /* pcmcia reg was set to zero at init time. Be careful when 171 * initializing a socket not to wipe out the settings of the 172 * other socket. 173 */ 174 pwr = bcsr->pcmcia; 175 pwr &= ~(0xf << sock*8); /* clear voltage settings */ 176 177 state->Vpp = 0; 178 switch(state->Vcc){ 179 case 0: /* Vcc 0 */ 180 pwr |= SET_VCC_VPP(0,0,sock); 181 break; 182 case 50: /* Vcc 5V */ 183 switch(state->Vpp) { 184 case 0: 185 pwr |= SET_VCC_VPP(2,0,sock); 186 break; 187 case 50: 188 pwr |= SET_VCC_VPP(2,1,sock); 189 break; 190 case 12: 191 pwr |= SET_VCC_VPP(2,2,sock); 192 break; 193 case 33: 194 default: 195 pwr |= SET_VCC_VPP(0,0,sock); 196 printk("%s: bad Vcc/Vpp (%d:%d)\n", 197 __func__, 198 state->Vcc, 199 state->Vpp); 200 break; 201 } 202 break; 203 case 33: /* Vcc 3.3V */ 204 switch(state->Vpp) { 205 case 0: 206 pwr |= SET_VCC_VPP(1,0,sock); 207 break; 208 case 12: 209 pwr |= SET_VCC_VPP(1,2,sock); 210 break; 211 case 33: 212 pwr |= SET_VCC_VPP(1,1,sock); 213 break; 214 case 50: 215 default: 216 pwr |= SET_VCC_VPP(0,0,sock); 217 printk("%s: bad Vcc/Vpp (%d:%d)\n", 218 __func__, 219 state->Vcc, 220 state->Vpp); 221 break; 222 } 223 break; 224 default: /* what's this ? */ 225 pwr |= SET_VCC_VPP(0,0,sock); 226 printk(KERN_ERR "%s: bad Vcc %d\n", 227 __func__, state->Vcc); 228 break; 229 } 230 231 bcsr->pcmcia = pwr; 232 au_sync_delay(300); 233 234 if (sock == 0) { 235 if (!(state->flags & SS_RESET)) { 236 pwr |= BCSR_PCMCIA_PC0DRVEN; 237 bcsr->pcmcia = pwr; 238 au_sync_delay(300); 239 pwr |= BCSR_PCMCIA_PC0RST; 240 bcsr->pcmcia = pwr; 241 au_sync_delay(100); 242 } 243 else { 244 pwr &= ~(BCSR_PCMCIA_PC0RST | BCSR_PCMCIA_PC0DRVEN); 245 bcsr->pcmcia = pwr; 246 au_sync_delay(100); 247 } 248 } 249 else { 250 if (!(state->flags & SS_RESET)) { 251 pwr |= BCSR_PCMCIA_PC1DRVEN; 252 bcsr->pcmcia = pwr; 253 au_sync_delay(300); 254 pwr |= BCSR_PCMCIA_PC1RST; 255 bcsr->pcmcia = pwr; 256 au_sync_delay(100); 257 } 258 else { 259 pwr &= ~(BCSR_PCMCIA_PC1RST | BCSR_PCMCIA_PC1DRVEN); 260 bcsr->pcmcia = pwr; 261 au_sync_delay(100); 262 } 263 } 264 return 0; 265} 266 267/* 268 * Enable card status IRQs on (re-)initialisation. This can 269 * be called at initialisation, power management event, or 270 * pcmcia event. 271 */ 272void db1x00_socket_init(struct au1000_pcmcia_socket *skt) 273{ 274 /* nothing to do for now */ 275} 276 277/* 278 * Disable card status IRQs and PCMCIA bus on suspend. 279 */ 280void db1x00_socket_suspend(struct au1000_pcmcia_socket *skt) 281{ 282 /* nothing to do for now */ 283} 284 285struct pcmcia_low_level db1x00_pcmcia_ops = { 286 .owner = THIS_MODULE, 287 288 .hw_init = db1x00_pcmcia_hw_init, 289 .hw_shutdown = db1x00_pcmcia_shutdown, 290 291 .socket_state = db1x00_pcmcia_socket_state, 292 .configure_socket = db1x00_pcmcia_configure_socket, 293 294 .socket_init = db1x00_socket_init, 295 .socket_suspend = db1x00_socket_suspend 296}; 297 298int au1x_board_init(struct device *dev) 299{ 300 int ret = -ENODEV; 301 bcsr->pcmcia = 0; /* turn off power, if it's not already off */ 302 au_sync_delay(2); 303 ret = au1x00_pcmcia_socket_probe(dev, &db1x00_pcmcia_ops, 0, 2); 304 return ret; 305}