This source file includes following definitions.
- cdirq
- xxs1500_pcmcia_configure
- xxs1500_pcmcia_get_status
- xxs1500_pcmcia_sock_init
- xxs1500_pcmcia_sock_suspend
- au1x00_pcmcia_set_io_map
- au1x00_pcmcia_set_mem_map
- xxs1500_pcmcia_probe
- xxs1500_pcmcia_remove
   1 
   2 
   3 
   4 
   5 
   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 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  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         
  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         
  85         switch (state->Vcc) {
  86         case 0:
  87                 gpio_set_value(GPIO_POWER, 1);  
  88                 break;
  89         case 33:
  90                 gpio_set_value(GPIO_POWER, 0);  
  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);  
 102                         gpio_set_value(GPIO_OUTEN, 1);  
 103                 } else {
 104                         gpio_set_value(GPIO_RESET, 0);  
 105                         gpio_set_value(GPIO_OUTEN, 0);  
 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         
 124         if (!gpio_get_value(GPIO_CDA) && !gpio_get_value(GPIO_CDB))
 125                 status |= SS_DETECT;
 126 
 127         
 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;    
 135                 break;
 136         case 3:                         
 137         default:
 138                 status |= SS_XVCARD;    
 139         }
 140 
 141         
 142         status |= gpio_get_value(GPIO_POWER) ? 0 : SS_POWERON;
 143 
 144         
 145         status |= gpio_get_value(GPIO_RESET) ? SS_RESET : SS_READY;
 146 
 147         
 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);   
 165         gpio_direction_output(GPIO_OUTEN, 1);   
 166         gpio_direction_output(GPIO_POWER, 1);   
 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         
 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         
 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         
 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 
 248 
 249 
 250 
 251 
 252 
 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         
 275 
 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");