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