linux/drivers/pcmcia/m32r_cfc.c
<<
>>
Prefs
   1/*
   2 *  drivers/pcmcia/m32r_cfc.c
   3 *
   4 *  Device driver for the CFC functionality of M32R.
   5 *
   6 *  Copyright (c) 2001, 2002, 2003, 2004
   7 *    Hiroyuki Kondo, Naoto Sugai, Hayato Fujiwara
   8 */
   9
  10#include <linux/module.h>
  11#include <linux/moduleparam.h>
  12#include <linux/init.h>
  13#include <linux/types.h>
  14#include <linux/fcntl.h>
  15#include <linux/string.h>
  16#include <linux/kernel.h>
  17#include <linux/errno.h>
  18#include <linux/timer.h>
  19#include <linux/slab.h>
  20#include <linux/ioport.h>
  21#include <linux/delay.h>
  22#include <linux/workqueue.h>
  23#include <linux/interrupt.h>
  24#include <linux/platform_device.h>
  25#include <linux/bitops.h>
  26#include <asm/irq.h>
  27#include <asm/io.h>
  28#include <asm/system.h>
  29
  30#include <pcmcia/cs_types.h>
  31#include <pcmcia/ss.h>
  32#include <pcmcia/cs.h>
  33
  34#undef MAX_IO_WIN       /* FIXME */
  35#define MAX_IO_WIN 1
  36#undef MAX_WIN          /* FIXME */
  37#define MAX_WIN 1
  38
  39#include "m32r_cfc.h"
  40
  41#ifdef CONFIG_PCMCIA_DEBUG
  42static int m32r_cfc_debug;
  43module_param(m32r_cfc_debug, int, 0644);
  44#define debug(lvl, fmt, arg...) do {                            \
  45        if (m32r_cfc_debug > (lvl))                             \
  46                printk(KERN_DEBUG "m32r_cfc: " fmt , ## arg);   \
  47} while (0)
  48#else
  49#define debug(n, args...) do { } while (0)
  50#endif
  51
  52/* Poll status interval -- 0 means default to interrupt */
  53static int poll_interval = 0;
  54
  55typedef enum pcc_space { as_none = 0, as_comm, as_attr, as_io } pcc_as_t;
  56
  57typedef struct pcc_socket {
  58        u_short                 type, flags;
  59        struct pcmcia_socket    socket;
  60        unsigned int            number;
  61        unsigned int            ioaddr;
  62        u_long                  mapaddr;
  63        u_long                  base;   /* PCC register base */
  64        u_char                  cs_irq1, cs_irq2, intr;
  65        pccard_io_map           io_map[MAX_IO_WIN];
  66        pccard_mem_map          mem_map[MAX_WIN];
  67        u_char                  io_win;
  68        u_char                  mem_win;
  69        pcc_as_t                current_space;
  70        u_char                  last_iodbex;
  71#ifdef CONFIG_PROC_FS
  72        struct proc_dir_entry *proc;
  73#endif
  74} pcc_socket_t;
  75
  76static int pcc_sockets = 0;
  77static pcc_socket_t socket[M32R_MAX_PCC] = {
  78        { 0, }, /* ... */
  79};
  80
  81/*====================================================================*/
  82
  83static unsigned int pcc_get(u_short, unsigned int);
  84static void pcc_set(u_short, unsigned int , unsigned int );
  85
  86static DEFINE_SPINLOCK(pcc_lock);
  87
  88#if !defined(CONFIG_PLAT_USRV)
  89static inline u_long pcc_port2addr(unsigned long port, int size) {
  90        u_long addr = 0;
  91        u_long odd;
  92
  93        if (size == 1) {        /* byte access */
  94                odd = (port&1) << 11;
  95                port -= port & 1;
  96                addr = CFC_IO_MAPBASE_BYTE - CFC_IOPORT_BASE + odd + port;
  97        } else if (size == 2)
  98                addr = CFC_IO_MAPBASE_WORD - CFC_IOPORT_BASE + port;
  99
 100        return addr;
 101}
 102#else   /* CONFIG_PLAT_USRV */
 103static inline u_long pcc_port2addr(unsigned long port, int size) {
 104        u_long odd;
 105        u_long addr = ((port - CFC_IOPORT_BASE) & 0xf000) << 8;
 106
 107        if (size == 1) {        /* byte access */
 108                odd = port & 1;
 109                port -= odd;
 110                odd <<= 11;
 111                addr = (addr | CFC_IO_MAPBASE_BYTE) + odd + (port & 0xfff);
 112        } else if (size == 2)   /* word access */
 113                addr = (addr | CFC_IO_MAPBASE_WORD) + (port & 0xfff);
 114
 115        return addr;
 116}
 117#endif  /* CONFIG_PLAT_USRV */
 118
 119void pcc_ioread_byte(int sock, unsigned long port, void *buf, size_t size,
 120        size_t nmemb, int flag)
 121{
 122        u_long addr;
 123        unsigned char *bp = (unsigned char *)buf;
 124        unsigned long flags;
 125
 126        debug(3, "m32r_cfc: pcc_ioread_byte: sock=%d, port=%#lx, buf=%p, "
 127                 "size=%u, nmemb=%d, flag=%d\n",
 128                  sock, port, buf, size, nmemb, flag);
 129
 130        addr = pcc_port2addr(port, 1);
 131        if (!addr) {
 132                printk("m32r_cfc:ioread_byte null port :%#lx\n",port);
 133                return;
 134        }
 135        debug(3, "m32r_cfc: pcc_ioread_byte: addr=%#lx\n", addr);
 136
 137        spin_lock_irqsave(&pcc_lock, flags);
 138        /* read Byte */
 139        while (nmemb--)
 140                *bp++ = readb(addr);
 141        spin_unlock_irqrestore(&pcc_lock, flags);
 142}
 143
 144void pcc_ioread_word(int sock, unsigned long port, void *buf, size_t size,
 145        size_t nmemb, int flag)
 146{
 147        u_long addr;
 148        unsigned short *bp = (unsigned short *)buf;
 149        unsigned long flags;
 150
 151        debug(3, "m32r_cfc: pcc_ioread_word: sock=%d, port=%#lx, "
 152                 "buf=%p, size=%u, nmemb=%d, flag=%d\n",
 153                 sock, port, buf, size, nmemb, flag);
 154
 155        if (size != 2)
 156                printk("m32r_cfc: ioread_word :illigal size %u : %#lx\n", size,
 157                        port);
 158        if (size == 9)
 159                printk("m32r_cfc: ioread_word :insw \n");
 160
 161        addr = pcc_port2addr(port, 2);
 162        if (!addr) {
 163                printk("m32r_cfc:ioread_word null port :%#lx\n",port);
 164                return;
 165        }
 166        debug(3, "m32r_cfc: pcc_ioread_word: addr=%#lx\n", addr);
 167
 168        spin_lock_irqsave(&pcc_lock, flags);
 169        /* read Word */
 170        while (nmemb--)
 171                *bp++ = readw(addr);
 172        spin_unlock_irqrestore(&pcc_lock, flags);
 173}
 174
 175void pcc_iowrite_byte(int sock, unsigned long port, void *buf, size_t size,
 176        size_t nmemb, int flag)
 177{
 178        u_long addr;
 179        unsigned char *bp = (unsigned char *)buf;
 180        unsigned long flags;
 181
 182        debug(3, "m32r_cfc: pcc_iowrite_byte: sock=%d, port=%#lx, "
 183                 "buf=%p, size=%u, nmemb=%d, flag=%d\n",
 184                 sock, port, buf, size, nmemb, flag);
 185
 186        /* write Byte */
 187        addr = pcc_port2addr(port, 1);
 188        if (!addr) {
 189                printk("m32r_cfc:iowrite_byte null port:%#lx\n",port);
 190                return;
 191        }
 192        debug(3, "m32r_cfc: pcc_iowrite_byte: addr=%#lx\n", addr);
 193
 194        spin_lock_irqsave(&pcc_lock, flags);
 195        while (nmemb--)
 196                writeb(*bp++, addr);
 197        spin_unlock_irqrestore(&pcc_lock, flags);
 198}
 199
 200void pcc_iowrite_word(int sock, unsigned long port, void *buf, size_t size,
 201        size_t nmemb, int flag)
 202{
 203        u_long addr;
 204        unsigned short *bp = (unsigned short *)buf;
 205        unsigned long flags;
 206
 207        debug(3, "m32r_cfc: pcc_iowrite_word: sock=%d, port=%#lx, "
 208                 "buf=%p, size=%u, nmemb=%d, flag=%d\n",
 209                 sock, port, buf, size, nmemb, flag);
 210
 211        if(size != 2)
 212                printk("m32r_cfc: iowrite_word :illigal size %u : %#lx\n",
 213                        size, port);
 214        if(size == 9)
 215                printk("m32r_cfc: iowrite_word :outsw \n");
 216
 217        addr = pcc_port2addr(port, 2);
 218        if (!addr) {
 219                printk("m32r_cfc:iowrite_word null addr :%#lx\n",port);
 220                return;
 221        }
 222#if 1
 223        if (addr & 1) {
 224                printk("m32r_cfc:iowrite_word port addr (%#lx):%#lx\n", port,
 225                        addr);
 226                return;
 227        }
 228#endif
 229        debug(3, "m32r_cfc: pcc_iowrite_word: addr=%#lx\n", addr);
 230
 231        spin_lock_irqsave(&pcc_lock, flags);
 232        while (nmemb--)
 233                writew(*bp++, addr);
 234        spin_unlock_irqrestore(&pcc_lock, flags);
 235}
 236
 237/*====================================================================*/
 238
 239#define IS_REGISTERED           0x2000
 240#define IS_ALIVE                0x8000
 241
 242typedef struct pcc_t {
 243        char                    *name;
 244        u_short                 flags;
 245} pcc_t;
 246
 247static pcc_t pcc[] = {
 248#if !defined(CONFIG_PLAT_USRV)
 249        { "m32r_cfc", 0 }, { "", 0 },
 250#else   /* CONFIG_PLAT_USRV */
 251        { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, { "m32r_cfc", 0 },
 252        { "m32r_cfc", 0 }, { "m32r_cfc", 0 }, { "", 0 },
 253#endif  /* CONFIG_PLAT_USRV */
 254};
 255
 256static irqreturn_t pcc_interrupt(int, void *);
 257
 258/*====================================================================*/
 259
 260static struct timer_list poll_timer;
 261
 262static unsigned int pcc_get(u_short sock, unsigned int reg)
 263{
 264        unsigned int val = inw(reg);
 265        debug(3, "m32r_cfc: pcc_get: reg(0x%08x)=0x%04x\n", reg, val);
 266        return val;
 267}
 268
 269
 270static void pcc_set(u_short sock, unsigned int reg, unsigned int data)
 271{
 272        outw(data, reg);
 273        debug(3, "m32r_cfc: pcc_set: reg(0x%08x)=0x%04x\n", reg, data);
 274}
 275
 276/*======================================================================
 277
 278        See if a card is present, powered up, in IO mode, and already
 279        bound to a (non PC Card) Linux driver.  We leave these alone.
 280
 281        We make an exception for cards that seem to be serial devices.
 282
 283======================================================================*/
 284
 285static int __init is_alive(u_short sock)
 286{
 287        unsigned int stat;
 288
 289        debug(3, "m32r_cfc: is_alive:\n");
 290
 291        printk("CF: ");
 292        stat = pcc_get(sock, (unsigned int)PLD_CFSTS);
 293        if (!stat)
 294                printk("No ");
 295        printk("Card is detected at socket %d : stat = 0x%08x\n", sock, stat);
 296        debug(3, "m32r_cfc: is_alive: sock stat is 0x%04x\n", stat);
 297
 298        return 0;
 299}
 300
 301static void add_pcc_socket(ulong base, int irq, ulong mapaddr,
 302                           unsigned int ioaddr)
 303{
 304        pcc_socket_t *t = &socket[pcc_sockets];
 305
 306        debug(3, "m32r_cfc: add_pcc_socket: base=%#lx, irq=%d, "
 307                 "mapaddr=%#lx, ioaddr=%08x\n",
 308                 base, irq, mapaddr, ioaddr);
 309
 310        /* add sockets */
 311        t->ioaddr = ioaddr;
 312        t->mapaddr = mapaddr;
 313#if !defined(CONFIG_PLAT_USRV)
 314        t->base = 0;
 315        t->flags = 0;
 316        t->cs_irq1 = irq;               // insert irq
 317        t->cs_irq2 = irq + 1;           // eject irq
 318#else   /* CONFIG_PLAT_USRV */
 319        t->base = base;
 320        t->flags = 0;
 321        t->cs_irq1 = 0;                 // insert irq
 322        t->cs_irq2 = 0;                 // eject irq
 323#endif  /* CONFIG_PLAT_USRV */
 324
 325        if (is_alive(pcc_sockets))
 326                t->flags |= IS_ALIVE;
 327
 328        /* add pcc */
 329#if !defined(CONFIG_PLAT_USRV)
 330        request_region((unsigned int)PLD_CFRSTCR, 0x20, "m32r_cfc");
 331#else   /* CONFIG_PLAT_USRV */
 332        {
 333                unsigned int reg_base;
 334
 335                reg_base = (unsigned int)PLD_CFRSTCR;
 336                reg_base |= pcc_sockets << 8;
 337                request_region(reg_base, 0x20, "m32r_cfc");
 338        }
 339#endif  /* CONFIG_PLAT_USRV */
 340        printk(KERN_INFO "  %s ", pcc[pcc_sockets].name);
 341        printk("pcc at 0x%08lx\n", t->base);
 342
 343        /* Update socket interrupt information, capabilities */
 344        t->socket.features |= (SS_CAP_PCCARD | SS_CAP_STATIC_MAP);
 345        t->socket.map_size = M32R_PCC_MAPSIZE;
 346        t->socket.io_offset = ioaddr;   /* use for io access offset */
 347        t->socket.irq_mask = 0;
 348#if !defined(CONFIG_PLAT_USRV)
 349        t->socket.pci_irq = PLD_IRQ_CFIREQ ;    /* card interrupt */
 350#else   /* CONFIG_PLAT_USRV */
 351        t->socket.pci_irq = PLD_IRQ_CF0 + pcc_sockets;
 352#endif  /* CONFIG_PLAT_USRV */
 353
 354#ifndef CONFIG_PLAT_USRV
 355        /* insert interrupt */
 356        request_irq(irq, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);
 357#ifndef CONFIG_PLAT_MAPPI3
 358        /* eject interrupt */
 359        request_irq(irq+1, pcc_interrupt, 0, "m32r_cfc", pcc_interrupt);
 360#endif
 361        debug(3, "m32r_cfc: enable CFMSK, RDYSEL\n");
 362        pcc_set(pcc_sockets, (unsigned int)PLD_CFIMASK, 0x01);
 363#endif  /* CONFIG_PLAT_USRV */
 364#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
 365        pcc_set(pcc_sockets, (unsigned int)PLD_CFCR1, 0x0200);
 366#endif
 367        pcc_sockets++;
 368
 369        return;
 370}
 371
 372
 373/*====================================================================*/
 374
 375static irqreturn_t pcc_interrupt(int irq, void *dev)
 376{
 377        int i;
 378        u_int events = 0;
 379        int handled = 0;
 380
 381        debug(3, "m32r_cfc: pcc_interrupt: irq=%d, dev=%p\n", irq, dev);
 382        for (i = 0; i < pcc_sockets; i++) {
 383                if (socket[i].cs_irq1 != irq && socket[i].cs_irq2 != irq)
 384                        continue;
 385
 386                handled = 1;
 387                debug(3, "m32r_cfc: pcc_interrupt: socket %d irq 0x%02x ",
 388                        i, irq);
 389                events |= SS_DETECT;    /* insert or eject */
 390                if (events)
 391                        pcmcia_parse_events(&socket[i].socket, events);
 392        }
 393        debug(3, "m32r_cfc: pcc_interrupt: done\n");
 394
 395        return IRQ_RETVAL(handled);
 396} /* pcc_interrupt */
 397
 398static void pcc_interrupt_wrapper(u_long data)
 399{
 400        debug(3, "m32r_cfc: pcc_interrupt_wrapper:\n");
 401        pcc_interrupt(0, NULL);
 402        init_timer(&poll_timer);
 403        poll_timer.expires = jiffies + poll_interval;
 404        add_timer(&poll_timer);
 405}
 406
 407/*====================================================================*/
 408
 409static int _pcc_get_status(u_short sock, u_int *value)
 410{
 411        u_int status;
 412
 413        debug(3, "m32r_cfc: _pcc_get_status:\n");
 414        status = pcc_get(sock, (unsigned int)PLD_CFSTS);
 415        *value = (status) ? SS_DETECT : 0;
 416        debug(3, "m32r_cfc: _pcc_get_status: status=0x%08x\n", status);
 417
 418#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT)
 419        if ( status ) {
 420                /* enable CF power */
 421                status = inw((unsigned int)PLD_CPCR);
 422                if (!(status & PLD_CPCR_CF)) {
 423                        debug(3, "m32r_cfc: _pcc_get_status: "
 424                                 "power on (CPCR=0x%08x)\n", status);
 425                        status |= PLD_CPCR_CF;
 426                        outw(status, (unsigned int)PLD_CPCR);
 427                        udelay(100);
 428                }
 429                *value |= SS_POWERON;
 430
 431                pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);/* enable buffer */
 432                udelay(100);
 433
 434                *value |= SS_READY;             /* always ready */
 435                *value |= SS_3VCARD;
 436        } else {
 437                /* disable CF power */
 438                status = inw((unsigned int)PLD_CPCR);
 439                status &= ~PLD_CPCR_CF;
 440                outw(status, (unsigned int)PLD_CPCR);
 441                udelay(100);
 442                debug(3, "m32r_cfc: _pcc_get_status: "
 443                         "power off (CPCR=0x%08x)\n", status);
 444        }
 445#elif defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 446        if ( status ) {
 447                status = pcc_get(sock, (unsigned int)PLD_CPCR);
 448                if (status == 0) { /* power off */
 449                        pcc_set(sock, (unsigned int)PLD_CPCR, 1);
 450                        pcc_set(sock, (unsigned int)PLD_CFBUFCR,0); /* force buffer off for ZA-36 */
 451                        udelay(50);
 452                }
 453                *value |= SS_POWERON;
 454
 455                pcc_set(sock, (unsigned int)PLD_CFBUFCR,0);
 456                udelay(50);
 457                pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0101);
 458                udelay(25); /* for IDE reset */
 459                pcc_set(sock, (unsigned int)PLD_CFRSTCR, 0x0100);
 460                mdelay(2);  /* for IDE reset */
 461
 462                *value |= SS_READY;
 463                *value |= SS_3VCARD;
 464        } else {
 465                /* disable CF power */
 466                pcc_set(sock, (unsigned int)PLD_CPCR, 0);
 467                udelay(100);
 468                debug(3, "m32r_cfc: _pcc_get_status: "
 469                         "power off (CPCR=0x%08x)\n", status);
 470        }
 471#else
 472#error no platform configuration
 473#endif
 474        debug(3, "m32r_cfc: _pcc_get_status: GetStatus(%d) = %#4.4x\n",
 475                 sock, *value);
 476        return 0;
 477} /* _get_status */
 478
 479/*====================================================================*/
 480
 481static int _pcc_set_socket(u_short sock, socket_state_t *state)
 482{
 483        debug(3, "m32r_cfc: SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 484                  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
 485                  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
 486
 487#if defined(CONFIG_PLAT_M32700UT) || defined(CONFIG_PLAT_USRV) || defined(CONFIG_PLAT_OPSPUT) || defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 488        if (state->Vcc) {
 489                if ((state->Vcc != 50) && (state->Vcc != 33))
 490                        return -EINVAL;
 491                /* accept 5V and 3.3V */
 492        }
 493#endif
 494        if (state->flags & SS_RESET) {
 495                debug(3, ":RESET\n");
 496                pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x101);
 497        }else{
 498                pcc_set(sock,(unsigned int)PLD_CFRSTCR,0x100);
 499        }
 500        if (state->flags & SS_OUTPUT_ENA){
 501                debug(3, ":OUTPUT_ENA\n");
 502                /* bit clear */
 503                pcc_set(sock,(unsigned int)PLD_CFBUFCR,0);
 504        } else {
 505                pcc_set(sock,(unsigned int)PLD_CFBUFCR,1);
 506        }
 507
 508#ifdef CONFIG_PCMCIA_DEBUG
 509        if(state->flags & SS_IOCARD){
 510                debug(3, ":IOCARD");
 511        }
 512        if (state->flags & SS_PWR_AUTO) {
 513                debug(3, ":PWR_AUTO");
 514        }
 515        if (state->csc_mask & SS_DETECT)
 516                debug(3, ":csc-SS_DETECT");
 517        if (state->flags & SS_IOCARD) {
 518                if (state->csc_mask & SS_STSCHG)
 519                        debug(3, ":STSCHG");
 520        } else {
 521                if (state->csc_mask & SS_BATDEAD)
 522                        debug(3, ":BATDEAD");
 523                if (state->csc_mask & SS_BATWARN)
 524                        debug(3, ":BATWARN");
 525                if (state->csc_mask & SS_READY)
 526                        debug(3, ":READY");
 527        }
 528        debug(3, "\n");
 529#endif
 530        return 0;
 531} /* _set_socket */
 532
 533/*====================================================================*/
 534
 535static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
 536{
 537        u_char map;
 538
 539        debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, "
 540                  "%#llx-%#llx)\n", sock, io->map, io->flags,
 541                  io->speed, (unsigned long long)io->start,
 542                  (unsigned long long)io->stop);
 543        map = io->map;
 544
 545        return 0;
 546} /* _set_io_map */
 547
 548/*====================================================================*/
 549
 550static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
 551{
 552
 553        u_char map = mem->map;
 554        u_long addr;
 555        pcc_socket_t *t = &socket[sock];
 556
 557        debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, "
 558                 "%#llx, %#x)\n", sock, map, mem->flags,
 559                 mem->speed, (unsigned long long)mem->static_start,
 560                 mem->card_start);
 561
 562        /*
 563         * sanity check
 564         */
 565        if ((map > MAX_WIN) || (mem->card_start > 0x3ffffff)){
 566                return -EINVAL;
 567        }
 568
 569        /*
 570         * de-activate
 571         */
 572        if ((mem->flags & MAP_ACTIVE) == 0) {
 573                t->current_space = as_none;
 574                return 0;
 575        }
 576
 577        /*
 578         * Set mode
 579         */
 580        if (mem->flags & MAP_ATTRIB) {
 581                t->current_space = as_attr;
 582        } else {
 583                t->current_space = as_comm;
 584        }
 585
 586        /*
 587         * Set address
 588         */
 589        addr = t->mapaddr + (mem->card_start & M32R_PCC_MAPMASK);
 590        mem->static_start = addr + mem->card_start;
 591
 592        return 0;
 593
 594} /* _set_mem_map */
 595
 596#if 0 /* driver model ordering issue */
 597/*======================================================================
 598
 599        Routines for accessing socket information and register dumps via
 600        /proc/bus/pccard/...
 601
 602======================================================================*/
 603
 604static ssize_t show_info(struct class_device *class_dev, char *buf)
 605{
 606        pcc_socket_t *s = container_of(class_dev, struct pcc_socket,
 607                socket.dev);
 608
 609        return sprintf(buf, "type:     %s\nbase addr:    0x%08lx\n",
 610                pcc[s->type].name, s->base);
 611}
 612
 613static ssize_t show_exca(struct class_device *class_dev, char *buf)
 614{
 615        /* FIXME */
 616
 617        return 0;
 618}
 619
 620static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
 621static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);
 622#endif
 623
 624/*====================================================================*/
 625
 626/* this is horribly ugly... proper locking needs to be done here at
 627 * some time... */
 628#define LOCKED(x) do {                                  \
 629        int retval;                                     \
 630        unsigned long flags;                            \
 631        spin_lock_irqsave(&pcc_lock, flags);            \
 632        retval = x;                                     \
 633        spin_unlock_irqrestore(&pcc_lock, flags);       \
 634        return retval;                                  \
 635} while (0)
 636
 637
 638static int pcc_get_status(struct pcmcia_socket *s, u_int *value)
 639{
 640        unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
 641
 642        if (socket[sock].flags & IS_ALIVE) {
 643                debug(3, "m32r_cfc: pcc_get_status: sock(%d) -EINVAL\n", sock);
 644                *value = 0;
 645                return -EINVAL;
 646        }
 647        debug(3, "m32r_cfc: pcc_get_status: sock(%d)\n", sock);
 648        LOCKED(_pcc_get_status(sock, value));
 649}
 650
 651static int pcc_set_socket(struct pcmcia_socket *s, socket_state_t *state)
 652{
 653        unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
 654
 655        if (socket[sock].flags & IS_ALIVE) {
 656                debug(3, "m32r_cfc: pcc_set_socket: sock(%d) -EINVAL\n", sock);
 657                return -EINVAL;
 658        }
 659        debug(3, "m32r_cfc: pcc_set_socket: sock(%d)\n", sock);
 660        LOCKED(_pcc_set_socket(sock, state));
 661}
 662
 663static int pcc_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
 664{
 665        unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
 666
 667        if (socket[sock].flags & IS_ALIVE) {
 668                debug(3, "m32r_cfc: pcc_set_io_map: sock(%d) -EINVAL\n", sock);
 669                return -EINVAL;
 670        }
 671        debug(3, "m32r_cfc: pcc_set_io_map: sock(%d)\n", sock);
 672        LOCKED(_pcc_set_io_map(sock, io));
 673}
 674
 675static int pcc_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
 676{
 677        unsigned int sock = container_of(s, struct pcc_socket, socket)->number;
 678
 679        if (socket[sock].flags & IS_ALIVE) {
 680                debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d) -EINVAL\n", sock);
 681                return -EINVAL;
 682        }
 683        debug(3, "m32r_cfc: pcc_set_mem_map: sock(%d)\n", sock);
 684        LOCKED(_pcc_set_mem_map(sock, mem));
 685}
 686
 687static int pcc_init(struct pcmcia_socket *s)
 688{
 689        debug(3, "m32r_cfc: pcc_init()\n");
 690        return 0;
 691}
 692
 693static struct pccard_operations pcc_operations = {
 694        .init                   = pcc_init,
 695        .get_status             = pcc_get_status,
 696        .set_socket             = pcc_set_socket,
 697        .set_io_map             = pcc_set_io_map,
 698        .set_mem_map            = pcc_set_mem_map,
 699};
 700
 701static int cfc_drv_pcmcia_suspend(struct platform_device *dev,
 702                                     pm_message_t state)
 703{
 704        return pcmcia_socket_dev_suspend(&dev->dev);
 705}
 706
 707static int cfc_drv_pcmcia_resume(struct platform_device *dev)
 708{
 709        return pcmcia_socket_dev_resume(&dev->dev);
 710}
 711/*====================================================================*/
 712
 713static struct platform_driver pcc_driver = {
 714        .driver = {
 715                .name           = "cfc",
 716                .owner          = THIS_MODULE,
 717        },
 718        .suspend        = cfc_drv_pcmcia_suspend,
 719        .resume         = cfc_drv_pcmcia_resume,
 720};
 721
 722static struct platform_device pcc_device = {
 723        .name = "cfc",
 724        .id = 0,
 725};
 726
 727/*====================================================================*/
 728
 729static int __init init_m32r_pcc(void)
 730{
 731        int i, ret;
 732
 733        ret = platform_driver_register(&pcc_driver);
 734        if (ret)
 735                return ret;
 736
 737        ret = platform_device_register(&pcc_device);
 738        if (ret){
 739                platform_driver_unregister(&pcc_driver);
 740                return ret;
 741        }
 742
 743#if defined(CONFIG_PLAT_MAPPI2) || defined(CONFIG_PLAT_MAPPI3)
 744        pcc_set(0, (unsigned int)PLD_CFCR0, 0x0f0f);
 745        pcc_set(0, (unsigned int)PLD_CFCR1, 0x0200);
 746#endif
 747
 748        pcc_sockets = 0;
 749
 750#if !defined(CONFIG_PLAT_USRV)
 751        add_pcc_socket(M32R_PCC0_BASE, PLD_IRQ_CFC_INSERT, CFC_ATTR_MAPBASE,
 752                       CFC_IOPORT_BASE);
 753#else   /* CONFIG_PLAT_USRV */
 754        {
 755                ulong base, mapaddr;
 756                unsigned int ioaddr;
 757
 758                for (i = 0 ; i < M32R_MAX_PCC ; i++) {
 759                        base = (ulong)PLD_CFRSTCR;
 760                        base = base | (i << 8);
 761                        ioaddr = (i + 1) << 12;
 762                        mapaddr = CFC_ATTR_MAPBASE | (i << 20);
 763                        add_pcc_socket(base, 0, mapaddr, ioaddr);
 764                }
 765        }
 766#endif  /* CONFIG_PLAT_USRV */
 767
 768        if (pcc_sockets == 0) {
 769                printk("socket is not found.\n");
 770                platform_device_unregister(&pcc_device);
 771                platform_driver_unregister(&pcc_driver);
 772                return -ENODEV;
 773        }
 774
 775        /* Set up interrupt handler(s) */
 776
 777        for (i = 0 ; i < pcc_sockets ; i++) {
 778                socket[i].socket.dev.parent = &pcc_device.dev;
 779                socket[i].socket.ops = &pcc_operations;
 780                socket[i].socket.resource_ops = &pccard_nonstatic_ops;
 781                socket[i].socket.owner = THIS_MODULE;
 782                socket[i].number = i;
 783                ret = pcmcia_register_socket(&socket[i].socket);
 784                if (!ret)
 785                        socket[i].flags |= IS_REGISTERED;
 786
 787#if 0   /* driver model ordering issue */
 788                class_device_create_file(&socket[i].socket.dev,
 789                                         &class_device_attr_info);
 790                class_device_create_file(&socket[i].socket.dev,
 791                                         &class_device_attr_exca);
 792#endif
 793        }
 794
 795        /* Finally, schedule a polling interrupt */
 796        if (poll_interval != 0) {
 797                poll_timer.function = pcc_interrupt_wrapper;
 798                poll_timer.data = 0;
 799                init_timer(&poll_timer);
 800                poll_timer.expires = jiffies + poll_interval;
 801                add_timer(&poll_timer);
 802        }
 803
 804        return 0;
 805} /* init_m32r_pcc */
 806
 807static void __exit exit_m32r_pcc(void)
 808{
 809        int i;
 810
 811        for (i = 0; i < pcc_sockets; i++)
 812                if (socket[i].flags & IS_REGISTERED)
 813                        pcmcia_unregister_socket(&socket[i].socket);
 814
 815        platform_device_unregister(&pcc_device);
 816        if (poll_interval != 0)
 817                del_timer_sync(&poll_timer);
 818
 819        platform_driver_unregister(&pcc_driver);
 820} /* exit_m32r_pcc */
 821
 822module_init(init_m32r_pcc);
 823module_exit(exit_m32r_pcc);
 824MODULE_LICENSE("Dual MPL/GPL");
 825/*====================================================================*/
 826