root/drivers/pcmcia/electra_cf.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. electra_cf_present
  2. electra_cf_ss_init
  3. electra_cf_timer
  4. electra_cf_irq
  5. electra_cf_get_status
  6. electra_cf_set_socket
  7. electra_cf_set_io_map
  8. electra_cf_set_mem_map
  9. electra_cf_probe
  10. electra_cf_remove

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

/* [<][>][^][v][top][bottom][index][help] */