root/drivers/pcmcia/xxs1500_ss.c

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

DEFINITIONS

This source file includes following definitions.
  1. cdirq
  2. xxs1500_pcmcia_configure
  3. xxs1500_pcmcia_get_status
  4. xxs1500_pcmcia_sock_init
  5. xxs1500_pcmcia_sock_suspend
  6. au1x00_pcmcia_set_io_map
  7. au1x00_pcmcia_set_mem_map
  8. xxs1500_pcmcia_probe
  9. xxs1500_pcmcia_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * PCMCIA socket code for the MyCable XXS1500 system.
   4  *
   5  * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>
   6  *
   7  */
   8 
   9 #include <linux/delay.h>
  10 #include <linux/gpio.h>
  11 #include <linux/interrupt.h>
  12 #include <linux/io.h>
  13 #include <linux/ioport.h>
  14 #include <linux/mm.h>
  15 #include <linux/module.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/pm.h>
  18 #include <linux/resource.h>
  19 #include <linux/slab.h>
  20 #include <linux/spinlock.h>
  21 
  22 #include <pcmcia/ss.h>
  23 #include <pcmcia/cistpl.h>
  24 
  25 #include <asm/irq.h>
  26 #include <asm/mach-au1x00/au1000.h>
  27 
  28 #define MEM_MAP_SIZE    0x400000
  29 #define IO_MAP_SIZE     0x1000
  30 
  31 
  32 /*
  33  * 3.3V cards only; all interfacing is done via gpios:
  34  *
  35  * 0/1:  carddetect (00 = card present, xx = huh)
  36  * 4:    card irq
  37  * 204:  reset (high-act)
  38  * 205:  buffer enable (low-act)
  39  * 208/209: card voltage key (00,01,10,11)
  40  * 210:  battwarn
  41  * 211:  batdead
  42  * 214:  power (low-act)
  43  */
  44 #define GPIO_CDA        0
  45 #define GPIO_CDB        1
  46 #define GPIO_CARDIRQ    4
  47 #define GPIO_RESET      204
  48 #define GPIO_OUTEN      205
  49 #define GPIO_VSL        208
  50 #define GPIO_VSH        209
  51 #define GPIO_BATTDEAD   210
  52 #define GPIO_BATTWARN   211
  53 #define GPIO_POWER      214
  54 
  55 struct xxs1500_pcmcia_sock {
  56         struct pcmcia_socket    socket;
  57         void            *virt_io;
  58 
  59         phys_addr_t     phys_io;
  60         phys_addr_t     phys_attr;
  61         phys_addr_t     phys_mem;
  62 
  63         /* previous flags for set_socket() */
  64         unsigned int old_flags;
  65 };
  66 
  67 #define to_xxs_socket(x) container_of(x, struct xxs1500_pcmcia_sock, socket)
  68 
  69 static irqreturn_t cdirq(int irq, void *data)
  70 {
  71         struct xxs1500_pcmcia_sock *sock = data;
  72 
  73         pcmcia_parse_events(&sock->socket, SS_DETECT);
  74 
  75         return IRQ_HANDLED;
  76 }
  77 
  78 static int xxs1500_pcmcia_configure(struct pcmcia_socket *skt,
  79                                     struct socket_state_t *state)
  80 {
  81         struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
  82         unsigned int changed;
  83 
  84         /* power control */
  85         switch (state->Vcc) {
  86         case 0:
  87                 gpio_set_value(GPIO_POWER, 1);  /* power off */
  88                 break;
  89         case 33:
  90                 gpio_set_value(GPIO_POWER, 0);  /* power on */
  91                 break;
  92         case 50:
  93         default:
  94                 return -EINVAL;
  95         }
  96 
  97         changed = state->flags ^ sock->old_flags;
  98 
  99         if (changed & SS_RESET) {
 100                 if (state->flags & SS_RESET) {
 101                         gpio_set_value(GPIO_RESET, 1);  /* assert reset */
 102                         gpio_set_value(GPIO_OUTEN, 1);  /* buffers off */
 103                 } else {
 104                         gpio_set_value(GPIO_RESET, 0);  /* deassert reset */
 105                         gpio_set_value(GPIO_OUTEN, 0);  /* buffers on */
 106                         msleep(500);
 107                 }
 108         }
 109 
 110         sock->old_flags = state->flags;
 111 
 112         return 0;
 113 }
 114 
 115 static int xxs1500_pcmcia_get_status(struct pcmcia_socket *skt,
 116                                      unsigned int *value)
 117 {
 118         unsigned int status;
 119         int i;
 120 
 121         status = 0;
 122 
 123         /* check carddetects: GPIO[0:1] must both be low */
 124         if (!gpio_get_value(GPIO_CDA) && !gpio_get_value(GPIO_CDB))
 125                 status |= SS_DETECT;
 126 
 127         /* determine card voltage: GPIO[208:209] binary value */
 128         i = (!!gpio_get_value(GPIO_VSL)) | ((!!gpio_get_value(GPIO_VSH)) << 1);
 129 
 130         switch (i) {
 131         case 0:
 132         case 1:
 133         case 2:
 134                 status |= SS_3VCARD;    /* 3V card */
 135                 break;
 136         case 3:                         /* 5V card, unsupported */
 137         default:
 138                 status |= SS_XVCARD;    /* treated as unsupported in core */
 139         }
 140 
 141         /* GPIO214: low active power switch */
 142         status |= gpio_get_value(GPIO_POWER) ? 0 : SS_POWERON;
 143 
 144         /* GPIO204: high-active reset line */
 145         status |= gpio_get_value(GPIO_RESET) ? SS_RESET : SS_READY;
 146 
 147         /* other stuff */
 148         status |= gpio_get_value(GPIO_BATTDEAD) ? 0 : SS_BATDEAD;
 149         status |= gpio_get_value(GPIO_BATTWARN) ? 0 : SS_BATWARN;
 150 
 151         *value = status;
 152 
 153         return 0;
 154 }
 155 
 156 static int xxs1500_pcmcia_sock_init(struct pcmcia_socket *skt)
 157 {
 158         gpio_direction_input(GPIO_CDA);
 159         gpio_direction_input(GPIO_CDB);
 160         gpio_direction_input(GPIO_VSL);
 161         gpio_direction_input(GPIO_VSH);
 162         gpio_direction_input(GPIO_BATTDEAD);
 163         gpio_direction_input(GPIO_BATTWARN);
 164         gpio_direction_output(GPIO_RESET, 1);   /* assert reset */
 165         gpio_direction_output(GPIO_OUTEN, 1);   /* disable buffers */
 166         gpio_direction_output(GPIO_POWER, 1);   /* power off */
 167 
 168         return 0;
 169 }
 170 
 171 static int xxs1500_pcmcia_sock_suspend(struct pcmcia_socket *skt)
 172 {
 173         return 0;
 174 }
 175 
 176 static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
 177                                     struct pccard_io_map *map)
 178 {
 179         struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
 180 
 181         map->start = (u32)sock->virt_io;
 182         map->stop = map->start + IO_MAP_SIZE;
 183 
 184         return 0;
 185 }
 186 
 187 static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
 188                                      struct pccard_mem_map *map)
 189 {
 190         struct xxs1500_pcmcia_sock *sock = to_xxs_socket(skt);
 191 
 192         if (map->flags & MAP_ATTRIB)
 193                 map->static_start = sock->phys_attr + map->card_start;
 194         else
 195                 map->static_start = sock->phys_mem + map->card_start;
 196 
 197         return 0;
 198 }
 199 
 200 static struct pccard_operations xxs1500_pcmcia_operations = {
 201         .init                   = xxs1500_pcmcia_sock_init,
 202         .suspend                = xxs1500_pcmcia_sock_suspend,
 203         .get_status             = xxs1500_pcmcia_get_status,
 204         .set_socket             = xxs1500_pcmcia_configure,
 205         .set_io_map             = au1x00_pcmcia_set_io_map,
 206         .set_mem_map            = au1x00_pcmcia_set_mem_map,
 207 };
 208 
 209 static int xxs1500_pcmcia_probe(struct platform_device *pdev)
 210 {
 211         struct xxs1500_pcmcia_sock *sock;
 212         struct resource *r;
 213         int ret, irq;
 214 
 215         sock = kzalloc(sizeof(struct xxs1500_pcmcia_sock), GFP_KERNEL);
 216         if (!sock)
 217                 return -ENOMEM;
 218 
 219         ret = -ENODEV;
 220 
 221         /* 36bit PCMCIA Attribute area address */
 222         r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
 223         if (!r) {
 224                 dev_err(&pdev->dev, "missing 'pcmcia-attr' resource!\n");
 225                 goto out0;
 226         }
 227         sock->phys_attr = r->start;
 228 
 229         /* 36bit PCMCIA Memory area address */
 230         r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
 231         if (!r) {
 232                 dev_err(&pdev->dev, "missing 'pcmcia-mem' resource!\n");
 233                 goto out0;
 234         }
 235         sock->phys_mem = r->start;
 236 
 237         /* 36bit PCMCIA IO area address */
 238         r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
 239         if (!r) {
 240                 dev_err(&pdev->dev, "missing 'pcmcia-io' resource!\n");
 241                 goto out0;
 242         }
 243         sock->phys_io = r->start;
 244 
 245 
 246         /*
 247          * PCMCIA client drivers use the inb/outb macros to access
 248          * the IO registers.  Since mips_io_port_base is added
 249          * to the access address of the mips implementation of
 250          * inb/outb, we need to subtract it here because we want
 251          * to access the I/O or MEM address directly, without
 252          * going through this "mips_io_port_base" mechanism.
 253          */
 254         sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
 255                                  mips_io_port_base);
 256 
 257         if (!sock->virt_io) {
 258                 dev_err(&pdev->dev, "cannot remap IO area\n");
 259                 ret = -ENOMEM;
 260                 goto out0;
 261         }
 262 
 263         sock->socket.ops        = &xxs1500_pcmcia_operations;
 264         sock->socket.owner      = THIS_MODULE;
 265         sock->socket.pci_irq    = gpio_to_irq(GPIO_CARDIRQ);
 266         sock->socket.features   = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
 267         sock->socket.map_size   = MEM_MAP_SIZE;
 268         sock->socket.io_offset  = (unsigned long)sock->virt_io;
 269         sock->socket.dev.parent = &pdev->dev;
 270         sock->socket.resource_ops = &pccard_static_ops;
 271 
 272         platform_set_drvdata(pdev, sock);
 273 
 274         /* setup carddetect irq: use one of the 2 GPIOs as an
 275          * edge detector.
 276          */
 277         irq = gpio_to_irq(GPIO_CDA);
 278         irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
 279         ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
 280         if (ret) {
 281                 dev_err(&pdev->dev, "cannot setup cd irq\n");
 282                 goto out1;
 283         }
 284 
 285         ret = pcmcia_register_socket(&sock->socket);
 286         if (ret) {
 287                 dev_err(&pdev->dev, "failed to register\n");
 288                 goto out2;
 289         }
 290 
 291         printk(KERN_INFO "MyCable XXS1500 PCMCIA socket services\n");
 292 
 293         return 0;
 294 
 295 out2:
 296         free_irq(gpio_to_irq(GPIO_CDA), sock);
 297 out1:
 298         iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
 299 out0:
 300         kfree(sock);
 301         return ret;
 302 }
 303 
 304 static int xxs1500_pcmcia_remove(struct platform_device *pdev)
 305 {
 306         struct xxs1500_pcmcia_sock *sock = platform_get_drvdata(pdev);
 307 
 308         pcmcia_unregister_socket(&sock->socket);
 309         free_irq(gpio_to_irq(GPIO_CDA), sock);
 310         iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
 311         kfree(sock);
 312 
 313         return 0;
 314 }
 315 
 316 static struct platform_driver xxs1500_pcmcia_socket_driver = {
 317         .driver = {
 318                 .name   = "xxs1500_pcmcia",
 319         },
 320         .probe          = xxs1500_pcmcia_probe,
 321         .remove         = xxs1500_pcmcia_remove,
 322 };
 323 
 324 module_platform_driver(xxs1500_pcmcia_socket_driver);
 325 
 326 MODULE_LICENSE("GPL");
 327 MODULE_DESCRIPTION("PCMCIA Socket Services for MyCable XXS1500 systems");
 328 MODULE_AUTHOR("Manuel Lauss");

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