aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/sa1111_generic.c
diff options
context:
space:
mode:
authorRussell King - ARM Linux <linux@arm.linux.org.uk>2009-03-29 14:42:44 -0400
committerDominik Brodowski <linux@dominikbrodowski.net>2009-11-09 02:30:11 -0500
commit701a5dc05ad99a06958b3f97cb69d99b47cebee3 (patch)
treef91ab0cb2179fa771dfb3c9929bc09c7580ec3f8 /drivers/pcmcia/sa1111_generic.c
parentda4f007375197d6683461b995d404b01a7fdf2f5 (diff)
PCMCIA: sa1111: wrap soc_pcmcia_socket to contain sa1111 specific data
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/sa1111_generic.c')
-rw-r--r--drivers/pcmcia/sa1111_generic.c58
1 files changed, 45 insertions, 13 deletions
diff --git a/drivers/pcmcia/sa1111_generic.c b/drivers/pcmcia/sa1111_generic.c
index a6793e30cf7..98c791537ca 100644
--- a/drivers/pcmcia/sa1111_generic.c
+++ b/drivers/pcmcia/sa1111_generic.c
@@ -30,9 +30,6 @@ static struct pcmcia_irqs irqs[] = {
30 30
31int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt) 31int sa1111_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
32{ 32{
33 if (skt->irq == NO_IRQ)
34 skt->irq = skt->nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
35
36 return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs)); 33 return soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
37} 34}
38 35
@@ -43,8 +40,8 @@ void sa1111_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
43 40
44void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) 41void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
45{ 42{
46 struct sa1111_dev *sadev = SA1111_DEV(skt->dev); 43 struct sa1111_pcmcia_socket *s = to_skt(skt);
47 unsigned long status = sa1111_readl(sadev->mapbase + SA1111_PCSR); 44 unsigned long status = sa1111_readl(s->dev->mapbase + SA1111_PCSR);
48 45
49 switch (skt->nr) { 46 switch (skt->nr) {
50 case 0: 47 case 0:
@@ -71,7 +68,7 @@ void sa1111_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_sta
71 68
72int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) 69int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
73{ 70{
74 struct sa1111_dev *sadev = SA1111_DEV(skt->dev); 71 struct sa1111_pcmcia_socket *s = to_skt(skt);
75 unsigned int pccr_skt_mask, pccr_set_mask, val; 72 unsigned int pccr_skt_mask, pccr_set_mask, val;
76 unsigned long flags; 73 unsigned long flags;
77 74
@@ -100,10 +97,10 @@ int sa1111_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_s
100 pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT; 97 pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
101 98
102 local_irq_save(flags); 99 local_irq_save(flags);
103 val = sa1111_readl(sadev->mapbase + SA1111_PCCR); 100 val = sa1111_readl(s->dev->mapbase + SA1111_PCCR);
104 val &= ~pccr_skt_mask; 101 val &= ~pccr_skt_mask;
105 val |= pccr_set_mask & pccr_skt_mask; 102 val |= pccr_set_mask & pccr_skt_mask;
106 sa1111_writel(val, sadev->mapbase + SA1111_PCCR); 103 sa1111_writel(val, s->dev->mapbase + SA1111_PCCR);
107 local_irq_restore(flags); 104 local_irq_restore(flags);
108 105
109 return 0; 106 return 0;
@@ -119,10 +116,45 @@ void sa1111_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
119 soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs)); 116 soc_pcmcia_disable_irqs(skt, irqs, ARRAY_SIZE(irqs));
120} 117}
121 118
119int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops,
120 int (*add)(struct soc_pcmcia_socket *))
121{
122 struct sa1111_pcmcia_socket *s;
123 int i, ret = 0;
124
125 s = kzalloc(sizeof(*s) * ops->nr, GFP_KERNEL);
126 if (!s)
127 return -ENODEV;
128
129 for (i = 0; i < ops->nr; i++) {
130 s = kzalloc(sizeof(*s), GFP_KERNEL);
131 if (!s)
132 return -ENOMEM;
133
134 s->soc.nr = ops->first + i;
135 s->soc.irq = s->soc.nr ? IRQ_S1_READY_NINT : IRQ_S0_READY_NINT;
136 s->soc.ops = ops;
137 s->soc.socket.owner = ops->owner;
138 s->soc.socket.dev.parent = &dev->dev;
139 s->dev = dev;
140
141 ret = add(&s->soc);
142 if (ret == 0) {
143 s->next = dev_get_drvdata(&dev->dev);
144 dev_set_drvdata(&dev->dev, s);
145 } else
146 kfree(s);
147 }
148
149 return ret;
150}
151
122static int pcmcia_probe(struct sa1111_dev *dev) 152static int pcmcia_probe(struct sa1111_dev *dev)
123{ 153{
124 void __iomem *base; 154 void __iomem *base;
125 155
156 dev_set_drvdata(&dev->dev, NULL);
157
126 if (!request_mem_region(dev->res.start, 512, 158 if (!request_mem_region(dev->res.start, 512,
127 SA1111_DRIVER_NAME(dev))) 159 SA1111_DRIVER_NAME(dev)))
128 return -EBUSY; 160 return -EBUSY;
@@ -152,15 +184,15 @@ static int pcmcia_probe(struct sa1111_dev *dev)
152 184
153static int __devexit pcmcia_remove(struct sa1111_dev *dev) 185static int __devexit pcmcia_remove(struct sa1111_dev *dev)
154{ 186{
155 struct skt_dev_info *sinfo = dev_get_drvdata(&dev->dev); 187 struct sa1111_pcmcia_socket *next, *s = dev_get_drvdata(&dev->dev);
156 int i;
157 188
158 dev_set_drvdata(&dev->dev, NULL); 189 dev_set_drvdata(&dev->dev, NULL);
159 190
160 for (i = 0; i < sinfo->nskt; i++) 191 for (; next = s->next, s; s = next) {
161 soc_pcmcia_remove_one(&sinfo->skt[i]); 192 soc_pcmcia_remove_one(&s->soc);
193 kfree(s);
194 }
162 195
163 kfree(sinfo);
164 release_mem_region(dev->res.start, 512); 196 release_mem_region(dev->res.start, 512);
165 return 0; 197 return 0;
166} 198}