aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/soc_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pcmcia/soc_common.c')
-rw-r--r--drivers/pcmcia/soc_common.c193
1 files changed, 127 insertions, 66 deletions
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index a0a9c2aa8d78..e0433f571962 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -32,6 +32,7 @@
32 32
33 33
34#include <linux/cpufreq.h> 34#include <linux/cpufreq.h>
35#include <linux/gpio.h>
35#include <linux/init.h> 36#include <linux/init.h>
36#include <linux/interrupt.h> 37#include <linux/interrupt.h>
37#include <linux/io.h> 38#include <linux/io.h>
@@ -49,6 +50,8 @@
49 50
50#include "soc_common.h" 51#include "soc_common.h"
51 52
53static irqreturn_t soc_common_pcmcia_interrupt(int irq, void *dev);
54
52#ifdef CONFIG_PCMCIA_DEBUG 55#ifdef CONFIG_PCMCIA_DEBUG
53 56
54static int pc_debug; 57static int pc_debug;
@@ -104,6 +107,93 @@ void soc_common_pcmcia_get_timing(struct soc_pcmcia_socket *skt,
104} 107}
105EXPORT_SYMBOL(soc_common_pcmcia_get_timing); 108EXPORT_SYMBOL(soc_common_pcmcia_get_timing);
106 109
110static void __soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt,
111 unsigned int nr)
112{
113 unsigned int i;
114
115 for (i = 0; i < nr; i++) {
116 if (skt->stat[i].irq)
117 free_irq(skt->stat[i].irq, skt);
118 if (gpio_is_valid(skt->stat[i].gpio))
119 gpio_free(skt->stat[i].gpio);
120 }
121
122 if (skt->ops->hw_shutdown)
123 skt->ops->hw_shutdown(skt);
124}
125
126static void soc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
127{
128 __soc_pcmcia_hw_shutdown(skt, ARRAY_SIZE(skt->stat));
129}
130
131static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
132{
133 int ret = 0, i;
134
135 if (skt->ops->hw_init) {
136 ret = skt->ops->hw_init(skt);
137 if (ret)
138 return ret;
139 }
140
141 for (i = 0; i < ARRAY_SIZE(skt->stat); i++) {
142 if (gpio_is_valid(skt->stat[i].gpio)) {
143 int irq;
144
145 ret = gpio_request_one(skt->stat[i].gpio, GPIOF_IN,
146 skt->stat[i].name);
147 if (ret) {
148 __soc_pcmcia_hw_shutdown(skt, i);
149 return ret;
150 }
151
152 irq = gpio_to_irq(skt->stat[i].gpio);
153
154 if (i == SOC_STAT_RDY)
155 skt->socket.pci_irq = irq;
156 else
157 skt->stat[i].irq = irq;
158 }
159
160 if (skt->stat[i].irq) {
161 ret = request_irq(skt->stat[i].irq,
162 soc_common_pcmcia_interrupt,
163 IRQF_TRIGGER_NONE,
164 skt->stat[i].name, skt);
165 if (ret) {
166 if (gpio_is_valid(skt->stat[i].gpio))
167 gpio_free(skt->stat[i].gpio);
168 __soc_pcmcia_hw_shutdown(skt, i);
169 return ret;
170 }
171 }
172 }
173
174 return ret;
175}
176
177static void soc_pcmcia_hw_enable(struct soc_pcmcia_socket *skt)
178{
179 int i;
180
181 for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
182 if (skt->stat[i].irq) {
183 irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_RISING);
184 irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_EDGE_BOTH);
185 }
186}
187
188static void soc_pcmcia_hw_disable(struct soc_pcmcia_socket *skt)
189{
190 int i;
191
192 for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
193 if (skt->stat[i].irq)
194 irq_set_irq_type(skt->stat[i].irq, IRQ_TYPE_NONE);
195}
196
107static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt) 197static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
108{ 198{
109 struct pcmcia_state state; 199 struct pcmcia_state state;
@@ -111,6 +201,22 @@ static unsigned int soc_common_pcmcia_skt_state(struct soc_pcmcia_socket *skt)
111 201
112 memset(&state, 0, sizeof(struct pcmcia_state)); 202 memset(&state, 0, sizeof(struct pcmcia_state));
113 203
204 /* Make battery voltage state report 'good' */
205 state.bvd1 = 1;
206 state.bvd2 = 1;
207
208 /* CD is active low by default */
209 if (gpio_is_valid(skt->stat[SOC_STAT_CD].gpio))
210 state.detect = !gpio_get_value(skt->stat[SOC_STAT_CD].gpio);
211
212 /* RDY and BVD are active high by default */
213 if (gpio_is_valid(skt->stat[SOC_STAT_RDY].gpio))
214 state.ready = !!gpio_get_value(skt->stat[SOC_STAT_RDY].gpio);
215 if (gpio_is_valid(skt->stat[SOC_STAT_BVD1].gpio))
216 state.bvd1 = !!gpio_get_value(skt->stat[SOC_STAT_BVD1].gpio);
217 if (gpio_is_valid(skt->stat[SOC_STAT_BVD2].gpio))
218 state.bvd2 = !!gpio_get_value(skt->stat[SOC_STAT_BVD2].gpio);
219
114 skt->ops->socket_state(skt, &state); 220 skt->ops->socket_state(skt, &state);
115 221
116 stat = state.detect ? SS_DETECT : 0; 222 stat = state.detect ? SS_DETECT : 0;
@@ -188,6 +294,7 @@ static int soc_common_pcmcia_sock_init(struct pcmcia_socket *sock)
188 debug(skt, 2, "initializing socket\n"); 294 debug(skt, 2, "initializing socket\n");
189 if (skt->ops->socket_init) 295 if (skt->ops->socket_init)
190 skt->ops->socket_init(skt); 296 skt->ops->socket_init(skt);
297 soc_pcmcia_hw_enable(skt);
191 return 0; 298 return 0;
192} 299}
193 300
@@ -207,6 +314,7 @@ static int soc_common_pcmcia_suspend(struct pcmcia_socket *sock)
207 314
208 debug(skt, 2, "suspending socket\n"); 315 debug(skt, 2, "suspending socket\n");
209 316
317 soc_pcmcia_hw_disable(skt);
210 if (skt->ops->socket_suspend) 318 if (skt->ops->socket_suspend)
211 skt->ops->socket_suspend(skt); 319 skt->ops->socket_suspend(skt);
212 320
@@ -526,69 +634,6 @@ static struct pccard_operations soc_common_pcmcia_operations = {
526}; 634};
527 635
528 636
529int soc_pcmcia_request_irqs(struct soc_pcmcia_socket *skt,
530 struct pcmcia_irqs *irqs, int nr)
531{
532 int i, res = 0;
533
534 for (i = 0; i < nr; i++) {
535 if (irqs[i].sock != skt->nr)
536 continue;
537 res = request_irq(irqs[i].irq, soc_common_pcmcia_interrupt,
538 IRQF_DISABLED, irqs[i].str, skt);
539 if (res)
540 break;
541 irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
542 }
543
544 if (res) {
545 printk(KERN_ERR "PCMCIA: request for IRQ%d failed (%d)\n",
546 irqs[i].irq, res);
547
548 while (i--)
549 if (irqs[i].sock == skt->nr)
550 free_irq(irqs[i].irq, skt);
551 }
552 return res;
553}
554EXPORT_SYMBOL(soc_pcmcia_request_irqs);
555
556void soc_pcmcia_free_irqs(struct soc_pcmcia_socket *skt,
557 struct pcmcia_irqs *irqs, int nr)
558{
559 int i;
560
561 for (i = 0; i < nr; i++)
562 if (irqs[i].sock == skt->nr)
563 free_irq(irqs[i].irq, skt);
564}
565EXPORT_SYMBOL(soc_pcmcia_free_irqs);
566
567void soc_pcmcia_disable_irqs(struct soc_pcmcia_socket *skt,
568 struct pcmcia_irqs *irqs, int nr)
569{
570 int i;
571
572 for (i = 0; i < nr; i++)
573 if (irqs[i].sock == skt->nr)
574 irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
575}
576EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
577
578void soc_pcmcia_enable_irqs(struct soc_pcmcia_socket *skt,
579 struct pcmcia_irqs *irqs, int nr)
580{
581 int i;
582
583 for (i = 0; i < nr; i++)
584 if (irqs[i].sock == skt->nr) {
585 irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
586 irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
587 }
588}
589EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
590
591
592static LIST_HEAD(soc_pcmcia_sockets); 637static LIST_HEAD(soc_pcmcia_sockets);
593static DEFINE_MUTEX(soc_pcmcia_sockets_lock); 638static DEFINE_MUTEX(soc_pcmcia_sockets_lock);
594 639
@@ -635,6 +680,21 @@ module_exit(soc_pcmcia_cpufreq_unregister);
635 680
636#endif 681#endif
637 682
683void soc_pcmcia_init_one(struct soc_pcmcia_socket *skt,
684 struct pcmcia_low_level *ops, struct device *dev)
685{
686 int i;
687
688 skt->ops = ops;
689 skt->socket.owner = ops->owner;
690 skt->socket.dev.parent = dev;
691 skt->socket.pci_irq = NO_IRQ;
692
693 for (i = 0; i < ARRAY_SIZE(skt->stat); i++)
694 skt->stat[i].gpio = -EINVAL;
695}
696EXPORT_SYMBOL(soc_pcmcia_init_one);
697
638void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt) 698void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
639{ 699{
640 mutex_lock(&soc_pcmcia_sockets_lock); 700 mutex_lock(&soc_pcmcia_sockets_lock);
@@ -642,8 +702,9 @@ void soc_pcmcia_remove_one(struct soc_pcmcia_socket *skt)
642 702
643 pcmcia_unregister_socket(&skt->socket); 703 pcmcia_unregister_socket(&skt->socket);
644 704
645 skt->ops->hw_shutdown(skt); 705 soc_pcmcia_hw_shutdown(skt);
646 706
707 /* should not be required; violates some lowlevel drivers */
647 soc_common_pcmcia_config_skt(skt, &dead_socket); 708 soc_common_pcmcia_config_skt(skt, &dead_socket);
648 709
649 list_del(&skt->node); 710 list_del(&skt->node);
@@ -700,7 +761,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
700 */ 761 */
701 skt->ops->set_timing(skt); 762 skt->ops->set_timing(skt);
702 763
703 ret = skt->ops->hw_init(skt); 764 ret = soc_pcmcia_hw_init(skt);
704 if (ret) 765 if (ret)
705 goto out_err_6; 766 goto out_err_6;
706 767
@@ -733,7 +794,7 @@ int soc_pcmcia_add_one(struct soc_pcmcia_socket *skt)
733 pcmcia_unregister_socket(&skt->socket); 794 pcmcia_unregister_socket(&skt->socket);
734 795
735 out_err_7: 796 out_err_7:
736 skt->ops->hw_shutdown(skt); 797 soc_pcmcia_hw_shutdown(skt);
737 out_err_6: 798 out_err_6:
738 list_del(&skt->node); 799 list_del(&skt->node);
739 mutex_unlock(&soc_pcmcia_sockets_lock); 800 mutex_unlock(&soc_pcmcia_sockets_lock);