1/* 2 * drivers/pcmcia/sa1100_shannon.c 3 * 4 * PCMCIA implementation routines for Shannon 5 * 6 */ 7#include <linux/kernel.h> 8#include <linux/sched.h> 9 10#include <asm/hardware.h> 11#include <asm/arch/shannon.h> 12#include <asm/irq.h> 13#include "sa1100_generic.h" 14 15static int shannon_pcmcia_init(struct pcmcia_init *init) 16{ 17 int irq, res; 18 19 /* All those are inputs */ 20 GPDR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | 21 SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); 22 GAFR &= ~(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1 | 23 SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1); 24 25 /* Set transition detect */ 26 set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_0 | SHANNON_GPIO_EJECT_1, GPIO_NO_EDGES); 27 set_GPIO_IRQ_edge(SHANNON_GPIO_RDY_0 | SHANNON_GPIO_RDY_1, GPIO_FALLING_EDGE); 28 29 /* Register interrupts */ 30 irq = SHANNON_IRQ_GPIO_EJECT_0; 31 res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA_CD_0", NULL); 32 if (res < 0) goto irq_err; 33 irq = SHANNON_IRQ_GPIO_EJECT_1; 34 res = request_irq(irq, init->handler, SA_INTERRUPT, "PCMCIA_CD_1", NULL); 35 if (res < 0) goto irq_err; 36 37 return 2; 38irq_err: 39 printk(KERN_ERR "%s: Request for IRQ %d failed\n", __FUNCTION__, irq); 40 return -1; 41} 42 43static int shannon_pcmcia_shutdown(void) 44{ 45 /* disable IRQs */ 46 free_irq(SHANNON_IRQ_GPIO_EJECT_0, NULL); 47 free_irq(SHANNON_IRQ_GPIO_EJECT_1, NULL); 48 49 return 0; 50} 51 52static int shannon_pcmcia_socket_state(struct pcmcia_state_array *state_array) 53{ 54 unsigned long levels; 55 56 memset(state_array->state, 0, 57 state_array->size * sizeof(struct pcmcia_state)); 58 59 levels = GPLR; 60 61 state_array->state[0].detect = (levels & SHANNON_GPIO_EJECT_0) ? 0 : 1; 62 state_array->state[0].ready = (levels & SHANNON_GPIO_RDY_0) ? 1 : 0; 63 state_array->state[0].wrprot = 0; /* Not available on Shannon. */ 64 state_array->state[0].bvd1 = 1; 65 state_array->state[0].bvd2 = 1; 66 state_array->state[0].vs_3v = 1; 67 state_array->state[0].vs_Xv = 0; 68 69 state_array->state[1].detect = (levels & SHANNON_GPIO_EJECT_1) ? 0 : 1; 70 state_array->state[1].ready = (levels & SHANNON_GPIO_RDY_1) ? 1 : 0; 71 state_array->state[1].wrprot = 0; /* Not available on Shannon. */ 72 state_array->state[1].bvd1 = 1; 73 state_array->state[1].bvd2 = 1; 74 state_array->state[1].vs_3v = 1; 75 state_array->state[1].vs_Xv = 0; 76 77 return 1; 78} 79 80static int shannon_pcmcia_get_irq_info(struct pcmcia_irq_info *info) 81{ 82 if (info->sock == 0) 83 info->irq = SHANNON_IRQ_GPIO_RDY_0; 84 else if (info->sock == 1) 85 info->irq = SHANNON_IRQ_GPIO_RDY_1; 86 else return -1; 87 88 return 0; 89} 90 91static int shannon_pcmcia_configure_socket(const struct pcmcia_configure *configure) 92{ 93 94 switch (configure->vcc) { 95 case 0: /* power off */; 96 printk(KERN_WARNING __FUNCTION__"(): CS asked for 0V, still applying 3.3V..\n"); 97 break; 98 case 50: 99 printk(KERN_WARNING __FUNCTION__"(): CS asked for 5V, applying 3.3V..\n"); 100 case 33: 101 break; 102 default: 103 printk(KERN_ERR __FUNCTION__"(): unrecognized Vcc %u\n", 104 configure->vcc); 105 return -1; 106 } 107 108 printk(KERN_WARNING __FUNCTION__"(): Warning, Can't perform reset\n"); 109 110 /* Silently ignore Vpp, output enable, speaker enable. */ 111 112 return 0; 113} 114 115static int shannon_pcmcia_socket_init(int sock) 116{ 117 if (sock == 0) 118 set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_0, GPIO_BOTH_EDGES); 119 else if (sock == 1) 120 set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_1, GPIO_BOTH_EDGES); 121 122 return 0; 123} 124 125static int shannon_pcmcia_socket_suspend(int sock) 126{ 127 if (sock == 0) 128 set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_0, GPIO_NO_EDGES); 129 else if (sock == 1) 130 set_GPIO_IRQ_edge(SHANNON_GPIO_EJECT_1, GPIO_NO_EDGES); 131 132 return 0; 133} 134 135struct pcmcia_low_level shannon_pcmcia_ops = { 136 init: shannon_pcmcia_init, 137 shutdown: shannon_pcmcia_shutdown, 138 socket_state: shannon_pcmcia_socket_state, 139 get_irq_info: shannon_pcmcia_get_irq_info, 140 configure_socket: shannon_pcmcia_configure_socket, 141 142 socket_init: shannon_pcmcia_socket_init, 143 socket_suspend: shannon_pcmcia_socket_suspend, 144}; 145