Merge branches 'misc', 'sa1100-for-next' and 'spectre' into for-linus
[sfrench/cifs-2.6.git] / drivers / pcmcia / pxa2xx_mainstone.c
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  */
14 #include <linux/gpio/consumer.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18 #include <linux/kernel.h>
19 #include <linux/errno.h>
20 #include <linux/platform_device.h>
21
22 #include <pcmcia/ss.h>
23
24 #include <asm/mach-types.h>
25
26 #include "soc_common.h"
27 #include "max1600.h"
28
29 static int mst_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
30 {
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);
55 }
56
57 static unsigned int mst_pcmcia_bvd1_status[2];
58
59 static void mst_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
60                                     struct pcmcia_state *state)
61 {
62         unsigned int flip = mst_pcmcia_bvd1_status[skt->nr] ^ state->bvd1;
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) {
70                 mst_pcmcia_bvd1_status[skt->nr] = state->bvd1;
71                 if (state->bvd1)
72                         enable_irq(skt->stat[SOC_STAT_BVD1].irq);
73                 else
74                         disable_irq(skt->stat[SOC_STAT_BVD2].irq);
75         }
76 }
77
78 static int mst_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
79                                        const socket_state_t *state)
80 {
81         return max1600_configure(skt->driver_data, state->Vcc, state->Vpp);
82 }
83
84 static struct pcmcia_low_level mst_pcmcia_ops __initdata = {
85         .owner                  = THIS_MODULE,
86         .hw_init                = mst_pcmcia_hw_init,
87         .socket_state           = mst_pcmcia_socket_state,
88         .configure_socket       = mst_pcmcia_configure_socket,
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
98         if (!machine_is_mainstone())
99                 return -ENODEV;
100
101         mst_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
102         if (!mst_pcmcia_device)
103                 return -ENOMEM;
104
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);
109
110         if (ret)
111                 platform_device_put(mst_pcmcia_device);
112
113         return ret;
114 }
115
116 static void __exit mst_pcmcia_exit(void)
117 {
118         platform_device_unregister(mst_pcmcia_device);
119 }
120
121 fs_initcall(mst_pcmcia_init);
122 module_exit(mst_pcmcia_exit);
123
124 MODULE_LICENSE("GPL");
125 MODULE_ALIAS("platform:pxa2xx-pcmcia");