Merge tag 'platform-drivers-x86-v4.19-1' of git://git.infradead.org/linux-platform...
[linux-2.6-microblaze.git] / drivers / pcmcia / electra_cf.c
1 /*
2  * Copyright (C) 2007 PA Semi, Inc
3  *
4  * Maintained by: Olof Johansson <olof@lixom.net>
5  *
6  * Based on drivers/pcmcia/omap_cf.c
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  */
22
23 #include <linux/module.h>
24 #include <linux/kernel.h>
25 #include <linux/sched.h>
26 #include <linux/platform_device.h>
27 #include <linux/errno.h>
28 #include <linux/init.h>
29 #include <linux/delay.h>
30 #include <linux/interrupt.h>
31 #include <linux/mm.h>
32 #include <linux/vmalloc.h>
33 #include <linux/of_address.h>
34 #include <linux/of_irq.h>
35 #include <linux/of_platform.h>
36 #include <linux/slab.h>
37
38 #include <pcmcia/ss.h>
39
40 static const char driver_name[] = "electra-cf";
41
42 struct electra_cf_socket {
43         struct pcmcia_socket    socket;
44
45         struct timer_list       timer;
46         unsigned                present:1;
47         unsigned                active:1;
48
49         struct platform_device  *ofdev;
50         unsigned long           mem_phys;
51         void __iomem            *mem_base;
52         unsigned long           mem_size;
53         void __iomem            *io_virt;
54         unsigned int            io_base;
55         unsigned int            io_size;
56         u_int                   irq;
57         struct resource         iomem;
58         void __iomem            *gpio_base;
59         int                     gpio_detect;
60         int                     gpio_vsense;
61         int                     gpio_3v;
62         int                     gpio_5v;
63 };
64
65 #define POLL_INTERVAL           (2 * HZ)
66
67
68 static int electra_cf_present(struct electra_cf_socket *cf)
69 {
70         unsigned int gpio;
71
72         gpio = in_le32(cf->gpio_base+0x40);
73         return !(gpio & (1 << cf->gpio_detect));
74 }
75
76 static int electra_cf_ss_init(struct pcmcia_socket *s)
77 {
78         return 0;
79 }
80
81 /* the timer is primarily to kick this socket's pccardd */
82 static void electra_cf_timer(struct timer_list *t)
83 {
84         struct electra_cf_socket *cf = from_timer(cf, t, timer);
85         int present = electra_cf_present(cf);
86
87         if (present != cf->present) {
88                 cf->present = present;
89                 pcmcia_parse_events(&cf->socket, SS_DETECT);
90         }
91
92         if (cf->active)
93                 mod_timer(&cf->timer, jiffies + POLL_INTERVAL);
94 }
95
96 static irqreturn_t electra_cf_irq(int irq, void *_cf)
97 {
98         struct electra_cf_socket *cf = _cf;
99
100         electra_cf_timer(&cf->timer);
101         return IRQ_HANDLED;
102 }
103
104 static int electra_cf_get_status(struct pcmcia_socket *s, u_int *sp)
105 {
106         struct electra_cf_socket *cf;
107
108         if (!sp)
109                 return -EINVAL;
110
111         cf = container_of(s, struct electra_cf_socket, socket);
112
113         /* NOTE CF is always 3VCARD */
114         if (electra_cf_present(cf)) {
115                 *sp = SS_READY | SS_DETECT | SS_POWERON | SS_3VCARD;
116
117                 s->pci_irq = cf->irq;
118         } else
119                 *sp = 0;
120         return 0;
121 }
122
123 static int electra_cf_set_socket(struct pcmcia_socket *sock,
124                                  struct socket_state_t *s)
125 {
126         unsigned int gpio;
127         unsigned int vcc;
128         struct electra_cf_socket *cf;
129
130         cf = container_of(sock, struct electra_cf_socket, socket);
131
132         /* "reset" means no power in our case */
133         vcc = (s->flags & SS_RESET) ? 0 : s->Vcc;
134
135         switch (vcc) {
136         case 0:
137                 gpio = 0;
138                 break;
139         case 33:
140                 gpio = (1 << cf->gpio_3v);
141                 break;
142         case 5:
143                 gpio = (1 << cf->gpio_5v);
144                 break;
145         default:
146                 return -EINVAL;
147         }
148
149         gpio |= 1 << (cf->gpio_3v + 16); /* enwr */
150         gpio |= 1 << (cf->gpio_5v + 16); /* enwr */
151         out_le32(cf->gpio_base+0x90, gpio);
152
153         pr_debug("%s: Vcc %d, io_irq %d, flags %04x csc %04x\n",
154                 driver_name, s->Vcc, s->io_irq, s->flags, s->csc_mask);
155
156         return 0;
157 }
158
159 static int electra_cf_set_io_map(struct pcmcia_socket *s,
160                                  struct pccard_io_map *io)
161 {
162         return 0;
163 }
164
165 static int electra_cf_set_mem_map(struct pcmcia_socket *s,
166                                   struct pccard_mem_map *map)
167 {
168         struct electra_cf_socket *cf;
169
170         if (map->card_start)
171                 return -EINVAL;
172         cf = container_of(s, struct electra_cf_socket, socket);
173         map->static_start = cf->mem_phys;
174         map->flags &= MAP_ACTIVE|MAP_ATTRIB;
175         if (!(map->flags & MAP_ATTRIB))
176                 map->static_start += 0x800;
177         return 0;
178 }
179
180 static struct pccard_operations electra_cf_ops = {
181         .init                   = electra_cf_ss_init,
182         .get_status             = electra_cf_get_status,
183         .set_socket             = electra_cf_set_socket,
184         .set_io_map             = electra_cf_set_io_map,
185         .set_mem_map            = electra_cf_set_mem_map,
186 };
187
188 static int electra_cf_probe(struct platform_device *ofdev)
189 {
190         struct device *device = &ofdev->dev;
191         struct device_node *np = ofdev->dev.of_node;
192         struct electra_cf_socket   *cf;
193         struct resource mem, io;
194         int status;
195         const unsigned int *prop;
196         int err;
197         struct vm_struct *area;
198
199         err = of_address_to_resource(np, 0, &mem);
200         if (err)
201                 return -EINVAL;
202
203         err = of_address_to_resource(np, 1, &io);
204         if (err)
205                 return -EINVAL;
206
207         cf = kzalloc(sizeof(*cf), GFP_KERNEL);
208         if (!cf)
209                 return -ENOMEM;
210
211         timer_setup(&cf->timer, electra_cf_timer, 0);
212         cf->irq = 0;
213
214         cf->ofdev = ofdev;
215         cf->mem_phys = mem.start;
216         cf->mem_size = PAGE_ALIGN(resource_size(&mem));
217         cf->mem_base = ioremap(cf->mem_phys, cf->mem_size);
218         cf->io_size = PAGE_ALIGN(resource_size(&io));
219
220         area = __get_vm_area(cf->io_size, 0, PHB_IO_BASE, PHB_IO_END);
221         if (area == NULL) {
222                 status = -ENOMEM;
223                 goto fail1;
224         }
225
226         cf->io_virt = (void __iomem *)(area->addr);
227
228         cf->gpio_base = ioremap(0xfc103000, 0x1000);
229         dev_set_drvdata(device, cf);
230
231         if (!cf->mem_base || !cf->io_virt || !cf->gpio_base ||
232             (__ioremap_at(io.start, cf->io_virt, cf->io_size,
233                   pgprot_val(pgprot_noncached(__pgprot(0)))) == NULL)) {
234                 dev_err(device, "can't ioremap ranges\n");
235                 status = -ENOMEM;
236                 goto fail1;
237         }
238
239
240         cf->io_base = (unsigned long)cf->io_virt - VMALLOC_END;
241
242         cf->iomem.start = (unsigned long)cf->mem_base;
243         cf->iomem.end = (unsigned long)cf->mem_base + (mem.end - mem.start);
244         cf->iomem.flags = IORESOURCE_MEM;
245
246         cf->irq = irq_of_parse_and_map(np, 0);
247
248         status = request_irq(cf->irq, electra_cf_irq, IRQF_SHARED,
249                              driver_name, cf);
250         if (status < 0) {
251                 dev_err(device, "request_irq failed\n");
252                 goto fail1;
253         }
254
255         cf->socket.pci_irq = cf->irq;
256
257         prop = of_get_property(np, "card-detect-gpio", NULL);
258         if (!prop)
259                 goto fail1;
260         cf->gpio_detect = *prop;
261
262         prop = of_get_property(np, "card-vsense-gpio", NULL);
263         if (!prop)
264                 goto fail1;
265         cf->gpio_vsense = *prop;
266
267         prop = of_get_property(np, "card-3v-gpio", NULL);
268         if (!prop)
269                 goto fail1;
270         cf->gpio_3v = *prop;
271
272         prop = of_get_property(np, "card-5v-gpio", NULL);
273         if (!prop)
274                 goto fail1;
275         cf->gpio_5v = *prop;
276
277         cf->socket.io_offset = cf->io_base;
278
279         /* reserve chip-select regions */
280         if (!request_mem_region(cf->mem_phys, cf->mem_size, driver_name)) {
281                 status = -ENXIO;
282                 dev_err(device, "Can't claim memory region\n");
283                 goto fail1;
284         }
285
286         if (!request_region(cf->io_base, cf->io_size, driver_name)) {
287                 status = -ENXIO;
288                 dev_err(device, "Can't claim I/O region\n");
289                 goto fail2;
290         }
291
292         cf->socket.owner = THIS_MODULE;
293         cf->socket.dev.parent = &ofdev->dev;
294         cf->socket.ops = &electra_cf_ops;
295         cf->socket.resource_ops = &pccard_static_ops;
296         cf->socket.features = SS_CAP_PCCARD | SS_CAP_STATIC_MAP |
297                                 SS_CAP_MEM_ALIGN;
298         cf->socket.map_size = 0x800;
299
300         status = pcmcia_register_socket(&cf->socket);
301         if (status < 0) {
302                 dev_err(device, "pcmcia_register_socket failed\n");
303                 goto fail3;
304         }
305
306         dev_info(device, "at mem 0x%lx io 0x%llx irq %d\n",
307                  cf->mem_phys, io.start, cf->irq);
308
309         cf->active = 1;
310         electra_cf_timer(&cf->timer);
311         return 0;
312
313 fail3:
314         release_region(cf->io_base, cf->io_size);
315 fail2:
316         release_mem_region(cf->mem_phys, cf->mem_size);
317 fail1:
318         if (cf->irq)
319                 free_irq(cf->irq, cf);
320
321         if (cf->io_virt)
322                 __iounmap_at(cf->io_virt, cf->io_size);
323         if (cf->mem_base)
324                 iounmap(cf->mem_base);
325         if (cf->gpio_base)
326                 iounmap(cf->gpio_base);
327         if (area)
328                 device_init_wakeup(&ofdev->dev, 0);
329         kfree(cf);
330         return status;
331
332 }
333
334 static int electra_cf_remove(struct platform_device *ofdev)
335 {
336         struct device *device = &ofdev->dev;
337         struct electra_cf_socket *cf;
338
339         cf = dev_get_drvdata(device);
340
341         cf->active = 0;
342         pcmcia_unregister_socket(&cf->socket);
343         free_irq(cf->irq, cf);
344         del_timer_sync(&cf->timer);
345
346         __iounmap_at(cf->io_virt, cf->io_size);
347         iounmap(cf->mem_base);
348         iounmap(cf->gpio_base);
349         release_mem_region(cf->mem_phys, cf->mem_size);
350         release_region(cf->io_base, cf->io_size);
351
352         kfree(cf);
353
354         return 0;
355 }
356
357 static const struct of_device_id electra_cf_match[] = {
358         {
359                 .compatible   = "electra-cf",
360         },
361         {},
362 };
363 MODULE_DEVICE_TABLE(of, electra_cf_match);
364
365 static struct platform_driver electra_cf_driver = {
366         .driver = {
367                 .name = driver_name,
368                 .of_match_table = electra_cf_match,
369         },
370         .probe    = electra_cf_probe,
371         .remove   = electra_cf_remove,
372 };
373
374 module_platform_driver(electra_cf_driver);
375
376 MODULE_LICENSE("GPL");
377 MODULE_AUTHOR("Olof Johansson <olof@lixom.net>");
378 MODULE_DESCRIPTION("PA Semi Electra CF driver");