1 /* 2 * drivers/pcmcia/sa1100_h3600.c 3 * 4 * PCMCIA implementation routines for H3600 5 * 6 */ 7 #include <linux/module.h> 8 #include <linux/kernel.h> 9 #include <linux/device.h> 10 #include <linux/interrupt.h> 11 #include <linux/init.h> 12 #include <linux/delay.h> 13 #include <linux/gpio.h> 14 15 #include <mach/hardware.h> 16 #include <asm/irq.h> 17 #include <asm/mach-types.h> 18 #include <mach/h3xxx.h> 19 20 #include "sa1100_generic.h" 21 22 static struct pcmcia_irqs irqs[] = { 23 { .sock = 0, .str = "PCMCIA CD0" }, /* .irq will be filled later */ 24 { .sock = 1, .str = "PCMCIA CD1" } 25 }; 26 27 static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 28 { 29 int err; 30 31 switch (skt->nr) { 32 case 0: 33 err = gpio_request(H3XXX_GPIO_PCMCIA_IRQ0, "PCMCIA IRQ0"); 34 if (err) 35 goto err00; 36 err = gpio_direction_input(H3XXX_GPIO_PCMCIA_IRQ0); 37 if (err) 38 goto err01; 39 skt->socket.pci_irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_IRQ0); 40 41 err = gpio_request(H3XXX_GPIO_PCMCIA_CD0, "PCMCIA CD0"); 42 if (err) 43 goto err01; 44 err = gpio_direction_input(H3XXX_GPIO_PCMCIA_CD0); 45 if (err) 46 goto err02; 47 irqs[0].irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_CD0); 48 49 err = gpio_request(H3XXX_EGPIO_OPT_NVRAM_ON, "OPT NVRAM ON"); 50 if (err) 51 goto err02; 52 err = gpio_direction_output(H3XXX_EGPIO_OPT_NVRAM_ON, 0); 53 if (err) 54 goto err03; 55 err = gpio_request(H3XXX_EGPIO_OPT_ON, "OPT ON"); 56 if (err) 57 goto err03; 58 err = gpio_direction_output(H3XXX_EGPIO_OPT_ON, 0); 59 if (err) 60 goto err04; 61 err = gpio_request(H3XXX_EGPIO_OPT_RESET, "OPT RESET"); 62 if (err) 63 goto err04; 64 err = gpio_direction_output(H3XXX_EGPIO_OPT_RESET, 0); 65 if (err) 66 goto err05; 67 err = gpio_request(H3XXX_EGPIO_CARD_RESET, "PCMCIA CARD RESET"); 68 if (err) 69 goto err05; 70 err = gpio_direction_output(H3XXX_EGPIO_CARD_RESET, 0); 71 if (err) 72 goto err06; 73 err = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); 74 if (err) 75 goto err06; 76 break; 77 case 1: 78 err = gpio_request(H3XXX_GPIO_PCMCIA_IRQ1, "PCMCIA IRQ1"); 79 if (err) 80 goto err10; 81 err = gpio_direction_input(H3XXX_GPIO_PCMCIA_IRQ1); 82 if (err) 83 goto err11; 84 skt->socket.pci_irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_IRQ1); 85 86 err = gpio_request(H3XXX_GPIO_PCMCIA_CD1, "PCMCIA CD1"); 87 if (err) 88 goto err11; 89 err = gpio_direction_input(H3XXX_GPIO_PCMCIA_CD1); 90 if (err) 91 goto err12; 92 irqs[1].irq = gpio_to_irq(H3XXX_GPIO_PCMCIA_CD1); 93 94 err = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); 95 if (err) 96 goto err12; 97 break; 98 } 99 return 0; 100 101 err06: gpio_free(H3XXX_EGPIO_CARD_RESET); 102 err05: gpio_free(H3XXX_EGPIO_OPT_RESET); 103 err04: gpio_free(H3XXX_EGPIO_OPT_ON); 104 err03: gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); 105 err02: gpio_free(H3XXX_GPIO_PCMCIA_CD0); 106 err01: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); 107 err00: return err; 108 109 err12: gpio_free(H3XXX_GPIO_PCMCIA_CD0); 110 err11: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); 111 err10: return err; 112 } 113 114 static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 115 { 116 soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs)); 117 118 switch (skt->nr) { 119 case 0: 120 /* Disable CF bus: */ 121 gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0); 122 gpio_set_value(H3XXX_EGPIO_OPT_ON, 0); 123 gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1); 124 125 gpio_free(H3XXX_EGPIO_CARD_RESET); 126 gpio_free(H3XXX_EGPIO_OPT_RESET); 127 gpio_free(H3XXX_EGPIO_OPT_ON); 128 gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); 129 gpio_free(H3XXX_GPIO_PCMCIA_CD0); 130 gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); 131 break; 132 case 1: 133 gpio_free(H3XXX_GPIO_PCMCIA_CD1); 134 gpio_free(H3XXX_GPIO_PCMCIA_IRQ1); 135 break; 136 } 137 } 138 139 static void 140 h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) 141 { 142 switch (skt->nr) { 143 case 0: 144 state->detect = !gpio_get_value(H3XXX_GPIO_PCMCIA_CD0); 145 state->ready = !!gpio_get_value(H3XXX_GPIO_PCMCIA_IRQ0); 146 state->bvd1 = 0; 147 state->bvd2 = 0; 148 state->wrprot = 0; /* Not available on H3600. */ 149 state->vs_3v = 0; 150 state->vs_Xv = 0; 151 break; 152 153 case 1: 154 state->detect = !gpio_get_value(H3XXX_GPIO_PCMCIA_CD1); 155 state->ready = !!gpio_get_value(H3XXX_GPIO_PCMCIA_IRQ1); 156 state->bvd1 = 0; 157 state->bvd2 = 0; 158 state->wrprot = 0; /* Not available on H3600. */ 159 state->vs_3v = 0; 160 state->vs_Xv = 0; 161 break; 162 } 163 } 164 165 static int 166 h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 167 { 168 if (state->Vcc != 0 && state->Vcc != 33 && state->Vcc != 50) { 169 printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n", 170 state->Vcc / 10, state->Vcc % 10); 171 return -1; 172 } 173 174 gpio_set_value(H3XXX_EGPIO_CARD_RESET, !!(state->flags & SS_RESET)); 175 176 /* Silently ignore Vpp, output enable, speaker enable. */ 177 178 return 0; 179 } 180 181 static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 182 { 183 /* Enable CF bus: */ 184 gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 1); 185 gpio_set_value(H3XXX_EGPIO_OPT_ON, 1); 186 gpio_set_value(H3XXX_EGPIO_OPT_RESET, 0); 187 188 msleep(10); 189 190 soc_pcmcia_enable_irqs(skt, irqs, ARRAY_SIZE(irqs)); 191 } 192 193 static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 194 { 195 soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); 196 197 /* 198 * FIXME: This doesn't fit well. We don't have the mechanism in 199 * the generic PCMCIA layer to deal with the idea of two sockets 200 * on one bus. We rely on the cs.c behaviour shutting down 201 * socket 0 then socket 1. 202 */ 203 if (skt->nr == 1) { 204 gpio_set_value(H3XXX_EGPIO_OPT_ON, 0); 205 gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0); 206 /* hmm, does this suck power? */ 207 gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1); 208 } 209 } 210 211 struct pcmcia_low_level h3600_pcmcia_ops = { 212 .owner = THIS_MODULE, 213 .hw_init = h3600_pcmcia_hw_init, 214 .hw_shutdown = h3600_pcmcia_hw_shutdown, 215 .socket_state = h3600_pcmcia_socket_state, 216 .configure_socket = h3600_pcmcia_configure_socket, 217 218 .socket_init = h3600_pcmcia_socket_init, 219 .socket_suspend = h3600_pcmcia_socket_suspend, 220 }; 221 222 int __devinit pcmcia_h3600_init(struct device *dev) 223 { 224 int ret = -ENODEV; 225 226 if (machine_is_h3600() || machine_is_h3100()) 227 ret = sa11xx_drv_pcmcia_probe(dev, &h3600_pcmcia_ops, 0, 2); 228 229 return ret; 230 } 231