1 /* 2 * Sharp SL-C7xx Series PCMCIA routines 3 * 4 * Copyright (c) 2004-2005 Richard Purdie 5 * 6 * Based on Sharp's 2.4 kernel patches and pxa2xx_mainstone.c 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 */ 13 14 #include <linux/module.h> 15 #include <linux/init.h> 16 #include <linux/kernel.h> 17 #include <linux/errno.h> 18 #include <linux/interrupt.h> 19 #include <linux/platform_device.h> 20 21 #include <asm/mach-types.h> 22 #include <asm/hardware.h> 23 #include <asm/irq.h> 24 #include <asm/hardware/scoop.h> 25 #ifdef CONFIG_SA1100_COLLIE 26 #include <asm/arch-sa1100/collie.h> 27 #else 28 #include <asm/arch-pxa/pxa-regs.h> 29 #endif 30 31 #include "soc_common.h" 32 33 #define NO_KEEP_VS 0x0001 34 35 static void sharpsl_pcmcia_init_reset(struct scoop_pcmcia_dev *scoopdev) 36 { 37 reset_scoop(scoopdev->dev); 38 scoopdev->keep_vs = NO_KEEP_VS; 39 scoopdev->keep_rd = 0; 40 } 41 42 static int sharpsl_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 43 { 44 int ret; 45 46 #ifndef CONFIG_SA1100_COLLIE 47 /* 48 * Setup default state of GPIO outputs 49 * before we enable them as outputs. 50 */ 51 GPSR(GPIO48_nPOE) = 52 GPIO_bit(GPIO48_nPOE) | 53 GPIO_bit(GPIO49_nPWE) | 54 GPIO_bit(GPIO50_nPIOR) | 55 GPIO_bit(GPIO51_nPIOW) | 56 GPIO_bit(GPIO52_nPCE_1) | 57 GPIO_bit(GPIO53_nPCE_2); 58 59 pxa_gpio_mode(GPIO48_nPOE_MD); 60 pxa_gpio_mode(GPIO49_nPWE_MD); 61 pxa_gpio_mode(GPIO50_nPIOR_MD); 62 pxa_gpio_mode(GPIO51_nPIOW_MD); 63 pxa_gpio_mode(GPIO52_nPCE_1_MD); 64 pxa_gpio_mode(GPIO53_nPCE_2_MD); 65 pxa_gpio_mode(GPIO54_pSKTSEL_MD); 66 pxa_gpio_mode(GPIO55_nPREG_MD); 67 pxa_gpio_mode(GPIO56_nPWAIT_MD); 68 pxa_gpio_mode(GPIO57_nIOIS16_MD); 69 #endif 70 71 /* Register interrupts */ 72 if (scoop_devs[skt->nr].cd_irq >= 0) { 73 struct pcmcia_irqs cd_irq; 74 75 cd_irq.sock = skt->nr; 76 cd_irq.irq = scoop_devs[skt->nr].cd_irq; 77 cd_irq.str = scoop_devs[skt->nr].cd_irq_str; 78 ret = soc_pcmcia_request_irqs(skt, &cd_irq, 1); 79 80 if (ret) { 81 printk(KERN_ERR "Request for Compact Flash IRQ failed\n"); 82 return ret; 83 } 84 } 85 86 skt->irq = scoop_devs[skt->nr].irq; 87 88 return 0; 89 } 90 91 static void sharpsl_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 92 { 93 if (scoop_devs[skt->nr].cd_irq >= 0) { 94 struct pcmcia_irqs cd_irq; 95 96 cd_irq.sock = skt->nr; 97 cd_irq.irq = scoop_devs[skt->nr].cd_irq; 98 cd_irq.str = scoop_devs[skt->nr].cd_irq_str; 99 soc_pcmcia_free_irqs(skt, &cd_irq, 1); 100 } 101 } 102 103 104 static void sharpsl_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 105 struct pcmcia_state *state) 106 { 107 unsigned short cpr, csr; 108 struct device *scoop = scoop_devs[skt->nr].dev; 109 110 cpr = read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR); 111 112 write_scoop_reg(scoop, SCOOP_IRM, 0x00FF); 113 write_scoop_reg(scoop, SCOOP_ISR, 0x0000); 114 write_scoop_reg(scoop, SCOOP_IRM, 0x0000); 115 csr = read_scoop_reg(scoop, SCOOP_CSR); 116 if (csr & 0x0004) { 117 /* card eject */ 118 write_scoop_reg(scoop, SCOOP_CDR, 0x0000); 119 scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; 120 } 121 else if (!(scoop_devs[skt->nr].keep_vs & NO_KEEP_VS)) { 122 /* keep vs1,vs2 */ 123 write_scoop_reg(scoop, SCOOP_CDR, 0x0000); 124 csr |= scoop_devs[skt->nr].keep_vs; 125 } 126 else if (cpr & 0x0003) { 127 /* power on */ 128 write_scoop_reg(scoop, SCOOP_CDR, 0x0000); 129 scoop_devs[skt->nr].keep_vs = (csr & 0x00C0); 130 } 131 else { 132 /* card detect */ 133 write_scoop_reg(scoop, SCOOP_CDR, 0x0002); 134 } 135 136 state->detect = (csr & 0x0004) ? 0 : 1; 137 state->ready = (csr & 0x0002) ? 1 : 0; 138 state->bvd1 = (csr & 0x0010) ? 1 : 0; 139 state->bvd2 = (csr & 0x0020) ? 1 : 0; 140 state->wrprot = (csr & 0x0008) ? 1 : 0; 141 state->vs_3v = (csr & 0x0040) ? 0 : 1; 142 state->vs_Xv = (csr & 0x0080) ? 0 : 1; 143 144 if ((cpr & 0x0080) && ((cpr & 0x8040) != 0x8040)) { 145 printk(KERN_ERR "sharpsl_pcmcia_socket_state(): CPR=%04X, Low voltage!\n", cpr); 146 } 147 148 } 149 150 151 static int sharpsl_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 152 const socket_state_t *state) 153 { 154 unsigned long flags; 155 struct device *scoop = scoop_devs[skt->nr].dev; 156 157 unsigned short cpr, ncpr, ccr, nccr, mcr, nmcr, imr, nimr; 158 159 switch (state->Vcc) { 160 case 0: break; 161 case 33: break; 162 case 50: break; 163 default: 164 printk(KERN_ERR "sharpsl_pcmcia_configure_socket(): bad Vcc %u\n", state->Vcc); 165 return -1; 166 } 167 168 if ((state->Vpp!=state->Vcc) && (state->Vpp!=0)) { 169 printk(KERN_ERR "CF slot cannot support Vpp %u\n", state->Vpp); 170 return -1; 171 } 172 173 local_irq_save(flags); 174 175 nmcr = (mcr = read_scoop_reg(scoop, SCOOP_MCR)) & ~0x0010; 176 ncpr = (cpr = read_scoop_reg(scoop, SCOOP_CPR)) & ~0x0083; 177 nccr = (ccr = read_scoop_reg(scoop, SCOOP_CCR)) & ~0x0080; 178 nimr = (imr = read_scoop_reg(scoop, SCOOP_IMR)) & ~0x003E; 179 180 ncpr |= (state->Vcc == 33) ? 0x0001 : 181 (state->Vcc == 50) ? 0x0002 : 0; 182 nmcr |= (state->flags&SS_IOCARD) ? 0x0010 : 0; 183 ncpr |= (state->flags&SS_OUTPUT_ENA) ? 0x0080 : 0; 184 nccr |= (state->flags&SS_RESET)? 0x0080: 0; 185 nimr |= ((skt->status&SS_DETECT) ? 0x0004 : 0)| 186 ((skt->status&SS_READY) ? 0x0002 : 0)| 187 ((skt->status&SS_BATDEAD)? 0x0010 : 0)| 188 ((skt->status&SS_BATWARN)? 0x0020 : 0)| 189 ((skt->status&SS_STSCHG) ? 0x0010 : 0)| 190 ((skt->status&SS_WRPROT) ? 0x0008 : 0); 191 192 if (!(ncpr & 0x0003)) { 193 scoop_devs[skt->nr].keep_rd = 0; 194 } else if (!scoop_devs[skt->nr].keep_rd) { 195 if (nccr & 0x0080) 196 scoop_devs[skt->nr].keep_rd = 1; 197 else 198 nccr |= 0x0080; 199 } 200 201 if (mcr != nmcr) 202 write_scoop_reg(scoop, SCOOP_MCR, nmcr); 203 if (cpr != ncpr) 204 write_scoop_reg(scoop, SCOOP_CPR, ncpr); 205 if (ccr != nccr) 206 write_scoop_reg(scoop, SCOOP_CCR, nccr); 207 if (imr != nimr) 208 write_scoop_reg(scoop, SCOOP_IMR, nimr); 209 210 local_irq_restore(flags); 211 212 return 0; 213 } 214 215 static void sharpsl_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 216 { 217 sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); 218 219 /* Enable interrupt */ 220 write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_IMR, 0x00C0); 221 write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_MCR, 0x0101); 222 scoop_devs[skt->nr].keep_vs = NO_KEEP_VS; 223 224 if (machine_is_collie()) 225 /* We need to disable SS_OUTPUT_ENA here. */ 226 write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); 227 } 228 229 static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 230 { 231 /* CF_BUS_OFF */ 232 sharpsl_pcmcia_init_reset(&scoop_devs[skt->nr]); 233 234 if (machine_is_collie()) 235 /* We need to disable SS_OUTPUT_ENA here. */ 236 write_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR, read_scoop_reg(scoop_devs[skt->nr].dev, SCOOP_CPR) & ~0x0080); 237 } 238 239 static struct pcmcia_low_level sharpsl_pcmcia_ops = { 240 .owner = THIS_MODULE, 241 .hw_init = sharpsl_pcmcia_hw_init, 242 .hw_shutdown = sharpsl_pcmcia_hw_shutdown, 243 .socket_state = sharpsl_pcmcia_socket_state, 244 .configure_socket = sharpsl_pcmcia_configure_socket, 245 .socket_init = sharpsl_pcmcia_socket_init, 246 .socket_suspend = sharpsl_pcmcia_socket_suspend, 247 .first = 0, 248 .nr = 0, 249 }; 250 251 static struct platform_device *sharpsl_pcmcia_device; 252 253 #ifdef CONFIG_SA1100_COLLIE 254 int __init pcmcia_collie_init(struct device *dev) 255 { 256 int ret = -ENODEV; 257 258 if (machine_is_collie()) 259 ret = sa11xx_drv_pcmcia_probe(dev, &sharpsl_pcmcia_ops, 0, 1); 260 261 return ret; 262 } 263 264 #else 265 266 static int __init sharpsl_pcmcia_init(void) 267 { 268 int ret; 269 270 sharpsl_pcmcia_ops.nr=scoop_num; 271 sharpsl_pcmcia_device = kmalloc(sizeof(*sharpsl_pcmcia_device), GFP_KERNEL); 272 if (!sharpsl_pcmcia_device) 273 return -ENOMEM; 274 275 memset(sharpsl_pcmcia_device, 0, sizeof(*sharpsl_pcmcia_device)); 276 sharpsl_pcmcia_device->name = "pxa2xx-pcmcia"; 277 sharpsl_pcmcia_device->dev.platform_data = &sharpsl_pcmcia_ops; 278 sharpsl_pcmcia_device->dev.parent=scoop_devs[0].dev; 279 280 ret = platform_device_register(sharpsl_pcmcia_device); 281 if (ret) 282 kfree(sharpsl_pcmcia_device); 283 284 return ret; 285 } 286 287 static void __exit sharpsl_pcmcia_exit(void) 288 { 289 /* 290 * This call is supposed to free our sharpsl_pcmcia_device. 291 * Unfortunately platform_device don't have a free method, and 292 * we can't assume it's free of any reference at this point so we 293 * can't free it either. 294 */ 295 platform_device_unregister(sharpsl_pcmcia_device); 296 } 297 298 fs_initcall(sharpsl_pcmcia_init); 299 module_exit(sharpsl_pcmcia_exit); 300 #endif 301 302 MODULE_DESCRIPTION("Sharp SL Series PCMCIA Support"); 303 MODULE_LICENSE("GPL"); 304