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 int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 23 { 24 int err; 25 26 switch (skt->nr) { 27 case 0: 28 skt->stat[SOC_STAT_CD].gpio = H3XXX_GPIO_PCMCIA_CD0; 29 skt->stat[SOC_STAT_CD].name = "PCMCIA CD0"; 30 skt->stat[SOC_STAT_RDY].gpio = H3XXX_GPIO_PCMCIA_IRQ0; 31 skt->stat[SOC_STAT_RDY].name = "PCMCIA IRQ0"; 32 33 err = gpio_request(H3XXX_EGPIO_OPT_NVRAM_ON, "OPT NVRAM ON"); 34 if (err) 35 goto err01; 36 err = gpio_direction_output(H3XXX_EGPIO_OPT_NVRAM_ON, 0); 37 if (err) 38 goto err03; 39 err = gpio_request(H3XXX_EGPIO_OPT_ON, "OPT ON"); 40 if (err) 41 goto err03; 42 err = gpio_direction_output(H3XXX_EGPIO_OPT_ON, 0); 43 if (err) 44 goto err04; 45 err = gpio_request(H3XXX_EGPIO_OPT_RESET, "OPT RESET"); 46 if (err) 47 goto err04; 48 err = gpio_direction_output(H3XXX_EGPIO_OPT_RESET, 0); 49 if (err) 50 goto err05; 51 err = gpio_request(H3XXX_EGPIO_CARD_RESET, "PCMCIA CARD RESET"); 52 if (err) 53 goto err05; 54 err = gpio_direction_output(H3XXX_EGPIO_CARD_RESET, 0); 55 if (err) 56 goto err06; 57 break; 58 case 1: 59 skt->stat[SOC_STAT_CD].gpio = H3XXX_GPIO_PCMCIA_CD1; 60 skt->stat[SOC_STAT_CD].name = "PCMCIA CD1"; 61 skt->stat[SOC_STAT_RDY].gpio = H3XXX_GPIO_PCMCIA_IRQ1; 62 skt->stat[SOC_STAT_RDY].name = "PCMCIA IRQ1"; 63 break; 64 } 65 return 0; 66 67 err06: gpio_free(H3XXX_EGPIO_CARD_RESET); 68 err05: gpio_free(H3XXX_EGPIO_OPT_RESET); 69 err04: gpio_free(H3XXX_EGPIO_OPT_ON); 70 err03: gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); 71 err01: gpio_free(H3XXX_GPIO_PCMCIA_IRQ0); 72 return err; 73 } 74 75 static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) 76 { 77 switch (skt->nr) { 78 case 0: 79 /* Disable CF bus: */ 80 gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0); 81 gpio_set_value(H3XXX_EGPIO_OPT_ON, 0); 82 gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1); 83 84 gpio_free(H3XXX_EGPIO_CARD_RESET); 85 gpio_free(H3XXX_EGPIO_OPT_RESET); 86 gpio_free(H3XXX_EGPIO_OPT_ON); 87 gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON); 88 break; 89 case 1: 90 break; 91 } 92 } 93 94 static void 95 h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) 96 { 97 state->bvd1 = 0; 98 state->bvd2 = 0; 99 state->vs_3v = 0; 100 state->vs_Xv = 0; 101 } 102 103 static int 104 h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 105 { 106 if (state->Vcc != 0 && state->Vcc != 33 && state->Vcc != 50) { 107 printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n", 108 state->Vcc / 10, state->Vcc % 10); 109 return -1; 110 } 111 112 gpio_set_value(H3XXX_EGPIO_CARD_RESET, !!(state->flags & SS_RESET)); 113 114 /* Silently ignore Vpp, output enable, speaker enable. */ 115 116 return 0; 117 } 118 119 static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt) 120 { 121 /* Enable CF bus: */ 122 gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 1); 123 gpio_set_value(H3XXX_EGPIO_OPT_ON, 1); 124 gpio_set_value(H3XXX_EGPIO_OPT_RESET, 0); 125 126 msleep(10); 127 } 128 129 static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) 130 { 131 /* 132 * FIXME: This doesn't fit well. We don't have the mechanism in 133 * the generic PCMCIA layer to deal with the idea of two sockets 134 * on one bus. We rely on the cs.c behaviour shutting down 135 * socket 0 then socket 1. 136 */ 137 if (skt->nr == 1) { 138 gpio_set_value(H3XXX_EGPIO_OPT_ON, 0); 139 gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0); 140 /* hmm, does this suck power? */ 141 gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1); 142 } 143 } 144 145 struct pcmcia_low_level h3600_pcmcia_ops = { 146 .owner = THIS_MODULE, 147 .hw_init = h3600_pcmcia_hw_init, 148 .hw_shutdown = h3600_pcmcia_hw_shutdown, 149 .socket_state = h3600_pcmcia_socket_state, 150 .configure_socket = h3600_pcmcia_configure_socket, 151 152 .socket_init = h3600_pcmcia_socket_init, 153 .socket_suspend = h3600_pcmcia_socket_suspend, 154 }; 155 156 int pcmcia_h3600_init(struct device *dev) 157 { 158 int ret = -ENODEV; 159 160 if (machine_is_h3600() || machine_is_h3100()) 161 ret = sa11xx_drv_pcmcia_probe(dev, &h3600_pcmcia_ops, 0, 2); 162 163 return ret; 164 } 165