Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
addff0fa MV |
2 | /* |
3 | * linux/drivers/pcmcia/pxa2xx_vpac270.c | |
4 | * | |
5 | * Driver for Voipac PXA270 PCMCIA and CF sockets | |
6 | * | |
9ed3fbf1 | 7 | * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@gmail.com> |
addff0fa MV |
8 | */ |
9 | ||
158f1e95 | 10 | #include <linux/gpio.h> |
addff0fa MV |
11 | #include <linux/module.h> |
12 | #include <linux/platform_device.h> | |
13 | ||
14 | #include <asm/mach-types.h> | |
15 | ||
addff0fa MV |
16 | #include <mach/vpac270.h> |
17 | ||
18 | #include "soc_common.h" | |
19 | ||
e27af7ed | 20 | static struct gpio vpac270_pcmcia_gpios[] = { |
e27af7ed MV |
21 | { GPIO107_VPAC270_PCMCIA_PPEN, GPIOF_INIT_LOW, "PCMCIA PPEN" }, |
22 | { GPIO11_VPAC270_PCMCIA_RESET, GPIOF_INIT_LOW, "PCMCIA Reset" }, | |
23 | }; | |
24 | ||
25 | static struct gpio vpac270_cf_gpios[] = { | |
e27af7ed MV |
26 | { GPIO16_VPAC270_CF_RESET, GPIOF_INIT_LOW, "CF Reset" }, |
27 | }; | |
28 | ||
addff0fa MV |
29 | static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) |
30 | { | |
31 | int ret; | |
32 | ||
33 | if (skt->nr == 0) { | |
e27af7ed MV |
34 | ret = gpio_request_array(vpac270_pcmcia_gpios, |
35 | ARRAY_SIZE(vpac270_pcmcia_gpios)); | |
addff0fa | 36 | |
a9bb5a4b RK |
37 | skt->stat[SOC_STAT_CD].gpio = GPIO84_VPAC270_PCMCIA_CD; |
38 | skt->stat[SOC_STAT_CD].name = "PCMCIA CD"; | |
39 | skt->stat[SOC_STAT_RDY].gpio = GPIO35_VPAC270_PCMCIA_RDY; | |
40 | skt->stat[SOC_STAT_RDY].name = "PCMCIA Ready"; | |
addff0fa | 41 | } else { |
e27af7ed MV |
42 | ret = gpio_request_array(vpac270_cf_gpios, |
43 | ARRAY_SIZE(vpac270_cf_gpios)); | |
addff0fa | 44 | |
a9bb5a4b RK |
45 | skt->stat[SOC_STAT_CD].gpio = GPIO17_VPAC270_CF_CD; |
46 | skt->stat[SOC_STAT_CD].name = "CF CD"; | |
47 | skt->stat[SOC_STAT_RDY].gpio = GPIO12_VPAC270_CF_RDY; | |
48 | skt->stat[SOC_STAT_RDY].name = "CF Ready"; | |
addff0fa | 49 | } |
e27af7ed MV |
50 | |
51 | return ret; | |
addff0fa MV |
52 | } |
53 | ||
54 | static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | |
55 | { | |
e27af7ed | 56 | if (skt->nr == 0) |
512b7938 | 57 | gpio_free_array(vpac270_pcmcia_gpios, |
e27af7ed MV |
58 | ARRAY_SIZE(vpac270_pcmcia_gpios)); |
59 | else | |
512b7938 | 60 | gpio_free_array(vpac270_cf_gpios, |
e27af7ed | 61 | ARRAY_SIZE(vpac270_cf_gpios)); |
addff0fa MV |
62 | } |
63 | ||
64 | static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | |
65 | struct pcmcia_state *state) | |
66 | { | |
addff0fa MV |
67 | state->vs_3v = 1; |
68 | state->vs_Xv = 0; | |
69 | } | |
70 | ||
71 | static int | |
72 | vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | |
73 | const socket_state_t *state) | |
74 | { | |
75 | if (skt->nr == 0) { | |
76 | gpio_set_value(GPIO11_VPAC270_PCMCIA_RESET, | |
77 | (state->flags & SS_RESET)); | |
78 | gpio_set_value(GPIO107_VPAC270_PCMCIA_PPEN, | |
79 | !(state->Vcc == 33 || state->Vcc == 50)); | |
80 | } else { | |
81 | gpio_set_value(GPIO16_VPAC270_CF_RESET, | |
82 | (state->flags & SS_RESET)); | |
83 | } | |
84 | ||
85 | return 0; | |
86 | } | |
87 | ||
addff0fa MV |
88 | static struct pcmcia_low_level vpac270_pcmcia_ops = { |
89 | .owner = THIS_MODULE, | |
90 | ||
91 | .first = 0, | |
92 | .nr = 2, | |
93 | ||
94 | .hw_init = vpac270_pcmcia_hw_init, | |
95 | .hw_shutdown = vpac270_pcmcia_hw_shutdown, | |
96 | ||
97 | .socket_state = vpac270_pcmcia_socket_state, | |
98 | .configure_socket = vpac270_pcmcia_configure_socket, | |
addff0fa MV |
99 | }; |
100 | ||
101 | static struct platform_device *vpac270_pcmcia_device; | |
102 | ||
103 | static int __init vpac270_pcmcia_init(void) | |
104 | { | |
105 | int ret; | |
106 | ||
107 | if (!machine_is_vpac270()) | |
108 | return -ENODEV; | |
109 | ||
110 | vpac270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | |
111 | if (!vpac270_pcmcia_device) | |
112 | return -ENOMEM; | |
113 | ||
114 | ret = platform_device_add_data(vpac270_pcmcia_device, | |
115 | &vpac270_pcmcia_ops, sizeof(vpac270_pcmcia_ops)); | |
116 | ||
117 | if (!ret) | |
118 | ret = platform_device_add(vpac270_pcmcia_device); | |
119 | ||
120 | if (ret) | |
121 | platform_device_put(vpac270_pcmcia_device); | |
122 | ||
123 | return ret; | |
124 | } | |
125 | ||
126 | static void __exit vpac270_pcmcia_exit(void) | |
127 | { | |
128 | platform_device_unregister(vpac270_pcmcia_device); | |
129 | } | |
130 | ||
131 | module_init(vpac270_pcmcia_init); | |
132 | module_exit(vpac270_pcmcia_exit); | |
133 | ||
134 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | |
135 | MODULE_DESCRIPTION("PCMCIA support for Voipac PXA270"); | |
136 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | |
137 | MODULE_LICENSE("GPL"); |