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