1/* 2 * drivers/pcmcia/sa1100_simpad.c 3 * 4 * PCMCIA implementation routines for simpad 5 * 6 */ 7#include <linux/module.h> 8#include <linux/kernel.h> 9#include <linux/device.h> 10#include <linux/init.h> 11 12#include <mach/hardware.h> 13#include <asm/mach-types.h> 14#include <asm/irq.h> 15#include <mach/simpad.h> 16#include "sa1100_generic.h" 17 18extern long get_cs3_shadow(void); 19extern void set_cs3_bit(int value); 20extern void clear_cs3_bit(int value); 21 22static struct pcmcia_irqs irqs[] = { 23 { 1, IRQ_GPIO_CF_CD, "CF_CD" }, 24}; 25 26static int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 27{ 28 29 clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); 30 31 skt->socket.pci_irq = IRQ_GPIO_CF_IRQ; 32 33 return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); 34} 35 36static void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 37{ 38 soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); 39 40 /* Disable CF bus: */ 41 //set_cs3_bit(PCMCIA_BUFF_DIS); 42 clear_cs3_bit(PCMCIA_RESET); 43} 44 45static void 46simpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt, 47 struct pcmcia_state *state) 48{ 49 unsigned long levels = GPLR; 50 long cs3reg = get_cs3_shadow(); 51 52 state->detect=((levels & GPIO_CF_CD)==0)?1:0; 53 state->ready=(levels & GPIO_CF_IRQ)?1:0; 54 state->bvd1=1; /* Not available on Simpad. */ 55 state->bvd2=1; /* Not available on Simpad. */ 56 state->wrprot=0; /* Not available on Simpad. */ 57 58 if((cs3reg & 0x0c) == 0x0c) { 59 state->vs_3v=0; 60 state->vs_Xv=0; 61 } else { 62 state->vs_3v=1; 63 state->vs_Xv=0; 64 } 65} 66 67static int 68simpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, 69 const socket_state_t *state) 70{ 71 unsigned long flags; 72 73 local_irq_save(flags); 74 75 /* Murphy: see table of MIC2562a-1 */ 76 switch (state->Vcc) { 77 case 0: 78 clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); 79 break; 80 81 case 33: 82 clear_cs3_bit(VCC_3V_EN|EN1); 83 set_cs3_bit(VCC_5V_EN|EN0); 84 break; 85 86 case 50: 87 clear_cs3_bit(VCC_5V_EN|EN1); 88 set_cs3_bit(VCC_3V_EN|EN0); 89 break; 90 91 default: 92 printk(KERN_ERR "%s(): unrecognized Vcc %u\n", 93 __func__, state->Vcc); 94 clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1); 95 local_irq_restore(flags); 96 return -1; 97 } 98 99 100 local_irq_restore(flags); 101 102 return 0; 103} 104 105static void simpad_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 106{ 107 soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); 108} 109 110static void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 111{ 112 soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); 113 set_cs3_bit(PCMCIA_RESET); 114} 115 116static struct pcmcia_low_level simpad_pcmcia_ops = { 117 .owner = THIS_MODULE, 118 .hw_init = simpad_pcmcia_hw_init, 119 .hw_shutdown = simpad_pcmcia_hw_shutdown, 120 .socket_state = simpad_pcmcia_socket_state, 121 .configure_socket = simpad_pcmcia_configure_socket, 122 .socket_init = simpad_pcmcia_socket_init, 123 .socket_suspend = simpad_pcmcia_socket_suspend, 124}; 125 126int __init pcmcia_simpad_init(struct device *dev) 127{ 128 int ret = -ENODEV; 129 130 if (machine_is_simpad()) 131 ret = sa11xx_drv_pcmcia_probe(dev, &simpad_pcmcia_ops, 1, 1); 132 133 return ret; 134} 135