]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/drivers/pcmcia/pxa2xx_mainstone.c | |
3 | * | |
4 | * Mainstone PCMCIA specific routines. | |
5 | * | |
6 | * Created: May 12, 2004 | |
7 | * Author: Nicolas Pitre | |
8 | * Copyright: MontaVista Software Inc. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License version 2 as | |
12 | * published by the Free Software Foundation. | |
13 | */ | |
34fdbe64 | 14 | #include <linux/gpio/consumer.h> |
1da177e4 LT |
15 | #include <linux/module.h> |
16 | #include <linux/init.h> | |
34fdbe64 | 17 | #include <linux/interrupt.h> |
1da177e4 LT |
18 | #include <linux/kernel.h> |
19 | #include <linux/errno.h> | |
d052d1be | 20 | #include <linux/platform_device.h> |
1da177e4 LT |
21 | |
22 | #include <pcmcia/ss.h> | |
23 | ||
04ba0f65 | 24 | #include <asm/mach-types.h> |
1da177e4 LT |
25 | |
26 | #include "soc_common.h" | |
34fdbe64 | 27 | #include "max1600.h" |
1da177e4 | 28 | |
1da177e4 LT |
29 | static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt) |
30 | { | |
34fdbe64 RK |
31 | struct device *dev = skt->socket.dev.parent; |
32 | struct max1600 *m; | |
33 | int ret; | |
34 | ||
35 | skt->stat[SOC_STAT_CD].name = skt->nr ? "bdetect" : "adetect"; | |
36 | skt->stat[SOC_STAT_BVD1].name = skt->nr ? "bbvd1" : "abvd1"; | |
37 | skt->stat[SOC_STAT_BVD2].name = skt->nr ? "bbvd2" : "abvd2"; | |
38 | skt->stat[SOC_STAT_RDY].name = skt->nr ? "bready" : "aready"; | |
39 | skt->stat[SOC_STAT_VS1].name = skt->nr ? "bvs1" : "avs1"; | |
40 | skt->stat[SOC_STAT_VS2].name = skt->nr ? "bvs2" : "avs2"; | |
41 | ||
42 | skt->gpio_reset = devm_gpiod_get(dev, skt->nr ? "breset" : "areset", | |
43 | GPIOD_OUT_HIGH); | |
44 | if (IS_ERR(skt->gpio_reset)) | |
45 | return PTR_ERR(skt->gpio_reset); | |
46 | ||
47 | ret = max1600_init(dev, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, | |
48 | MAX1600_CODE_HIGH); | |
49 | if (ret) | |
50 | return ret; | |
51 | ||
52 | skt->driver_data = m; | |
53 | ||
54 | return soc_pcmcia_request_gpiods(skt); | |
1da177e4 LT |
55 | } |
56 | ||
34fdbe64 | 57 | static unsigned int mst_pcmcia_bvd1_status[2]; |
1da177e4 LT |
58 | |
59 | static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | |
60 | struct pcmcia_state *state) | |
61 | { | |
34fdbe64 | 62 | unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1; |
1da177e4 LT |
63 | |
64 | /* | |
65 | * Workaround for STSCHG which can't be deasserted: | |
66 | * We therefore disable/enable corresponding IRQs | |
67 | * as needed to avoid IRQ locks. | |
68 | */ | |
69 | if (flip) { | |
34fdbe64 RK |
70 | mst_pcmcia_bvd1_status[skt->nr] = state->bvd1; |
71 | if (state->bvd1) | |
72 | enable_irq(skt->stat[SOC_STAT_BVD1].irq); | |
1da177e4 | 73 | else |
34fdbe64 | 74 | disable_irq(skt->stat[SOC_STAT_BVD2].irq); |
1da177e4 | 75 | } |
1da177e4 LT |
76 | } |
77 | ||
78 | static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | |
79 | const socket_state_t *state) | |
80 | { | |
34fdbe64 | 81 | return max1600_configure(skt->driver_data, state->Vcc, state->Vpp); |
1da177e4 LT |
82 | } |
83 | ||
4e5e8de0 | 84 | static struct pcmcia_low_level mst_pcmcia_ops __initdata = { |
1da177e4 LT |
85 | .owner = THIS_MODULE, |
86 | .hw_init = mst_pcmcia_hw_init, | |
1da177e4 LT |
87 | .socket_state = mst_pcmcia_socket_state, |
88 | .configure_socket = mst_pcmcia_configure_socket, | |
1da177e4 LT |
89 | .nr = 2, |
90 | }; | |
91 | ||
92 | static struct platform_device *mst_pcmcia_device; | |
93 | ||
94 | static int __init mst_pcmcia_init(void) | |
95 | { | |
96 | int ret; | |
97 | ||
04ba0f65 RK |
98 | if (!machine_is_mainstone()) |
99 | return -ENODEV; | |
100 | ||
b016450f | 101 | mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); |
1da177e4 LT |
102 | if (!mst_pcmcia_device) |
103 | return -ENOMEM; | |
b016450f | 104 | |
4e5e8de0 RK |
105 | ret = platform_device_add_data(mst_pcmcia_device, &mst_pcmcia_ops, |
106 | sizeof(mst_pcmcia_ops)); | |
107 | if (ret == 0) | |
108 | ret = platform_device_add(mst_pcmcia_device); | |
b016450f | 109 | |
1da177e4 | 110 | if (ret) |
b016450f | 111 | platform_device_put(mst_pcmcia_device); |
1da177e4 LT |
112 | |
113 | return ret; | |
114 | } | |
115 | ||
116 | static void __exit mst_pcmcia_exit(void) | |
117 | { | |
1da177e4 LT |
118 | platform_device_unregister(mst_pcmcia_device); |
119 | } | |
120 | ||
f36598ae | 121 | fs_initcall(mst_pcmcia_init); |
1da177e4 LT |
122 | module_exit(mst_pcmcia_exit); |
123 | ||
124 | MODULE_LICENSE("GPL"); | |
43cc71ee | 125 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); |