linux/drivers/pcmcia/db1xxx_ss.c
<<
>>
Prefs
   1/*
   2 * PCMCIA socket code for the Alchemy Db1xxx/Pb1xxx boards.
   3 *
   4 * Copyright (c) 2009 Manuel Lauss <manuel.lauss@gmail.com>
   5 *
   6 */
   7
   8/* This is a fairly generic PCMCIA socket driver suitable for the
   9 * following Alchemy Development boards:
  10 *  Db1000, Db/Pb1500, Db/Pb1100, Db/Pb1550, Db/Pb1200.
  11 *
  12 * The Db1000 is used as a reference:  Per-socket card-, carddetect- and
  13 *  statuschange IRQs connected to SoC GPIOs, control and status register
  14 *  bits arranged in per-socket groups in an external PLD.  All boards
  15 *  listed here use this layout, including bit positions and meanings.
  16 *  Of course there are exceptions in later boards:
  17 *
  18 *      - Pb1100/Pb1500:  single socket only; voltage key bits VS are
  19 *                        at STATUS[5:4] (instead of STATUS[1:0]).
  20 *      - Au1200-based:   additional card-eject irqs, irqs not gpios!
  21 */
  22
  23#include <linux/delay.h>
  24#include <linux/gpio.h>
  25#include <linux/interrupt.h>
  26#include <linux/pm.h>
  27#include <linux/platform_device.h>
  28#include <linux/resource.h>
  29#include <linux/slab.h>
  30#include <linux/spinlock.h>
  31
  32#include <pcmcia/cs_types.h>
  33#include <pcmcia/ss.h>
  34
  35#include <asm/mach-au1x00/au1000.h>
  36#include <asm/mach-db1x00/bcsr.h>
  37
  38#define MEM_MAP_SIZE    0x400000
  39#define IO_MAP_SIZE     0x1000
  40
  41struct db1x_pcmcia_sock {
  42        struct pcmcia_socket    socket;
  43        int             nr;             /* socket number */
  44        void            *virt_io;
  45
  46        phys_addr_t     phys_io;
  47        phys_addr_t     phys_attr;
  48        phys_addr_t     phys_mem;
  49
  50        /* previous flags for set_socket() */
  51        unsigned int old_flags;
  52
  53        /* interrupt sources: linux irq numbers! */
  54        int     insert_irq;     /* default carddetect irq */
  55        int     stschg_irq;     /* card-status-change irq */
  56        int     card_irq;       /* card irq */
  57        int     eject_irq;      /* db1200/pb1200 have these */
  58
  59#define BOARD_TYPE_DEFAULT      0       /* most boards */
  60#define BOARD_TYPE_DB1200       1       /* IRQs aren't gpios */
  61#define BOARD_TYPE_PB1100       2       /* VS bits slightly different */
  62        int     board_type;
  63};
  64
  65#define to_db1x_socket(x) container_of(x, struct db1x_pcmcia_sock, socket)
  66
  67/* DB/PB1200: check CPLD SIGSTATUS register bit 10/12 */
  68static int db1200_card_inserted(struct db1x_pcmcia_sock *sock)
  69{
  70        unsigned short sigstat;
  71
  72        sigstat = bcsr_read(BCSR_SIGSTAT);
  73        return sigstat & 1 << (8 + 2 * sock->nr);
  74}
  75
  76/* carddetect gpio: low-active */
  77static int db1000_card_inserted(struct db1x_pcmcia_sock *sock)
  78{
  79        return !gpio_get_value(irq_to_gpio(sock->insert_irq));
  80}
  81
  82static int db1x_card_inserted(struct db1x_pcmcia_sock *sock)
  83{
  84        switch (sock->board_type) {
  85        case BOARD_TYPE_DB1200:
  86                return db1200_card_inserted(sock);
  87        default:
  88                return db1000_card_inserted(sock);
  89        }
  90}
  91
  92/* STSCHG tends to bounce heavily when cards are inserted/ejected.
  93 * To avoid this, the interrupt is normally disabled and only enabled
  94 * after reset to a card has been de-asserted.
  95 */
  96static inline void set_stschg(struct db1x_pcmcia_sock *sock, int en)
  97{
  98        if (sock->stschg_irq != -1) {
  99                if (en)
 100                        enable_irq(sock->stschg_irq);
 101                else
 102                        disable_irq(sock->stschg_irq);
 103        }
 104}
 105
 106static irqreturn_t db1000_pcmcia_cdirq(int irq, void *data)
 107{
 108        struct db1x_pcmcia_sock *sock = data;
 109
 110        pcmcia_parse_events(&sock->socket, SS_DETECT);
 111
 112        return IRQ_HANDLED;
 113}
 114
 115static irqreturn_t db1000_pcmcia_stschgirq(int irq, void *data)
 116{
 117        struct db1x_pcmcia_sock *sock = data;
 118
 119        pcmcia_parse_events(&sock->socket, SS_STSCHG);
 120
 121        return IRQ_HANDLED;
 122}
 123
 124static irqreturn_t db1200_pcmcia_cdirq(int irq, void *data)
 125{
 126        struct db1x_pcmcia_sock *sock = data;
 127
 128        /* Db/Pb1200 have separate per-socket insertion and ejection
 129         * interrupts which stay asserted as long as the card is
 130         * inserted/missing.  The one which caused us to be called
 131         * needs to be disabled and the other one enabled.
 132         */
 133        if (irq == sock->insert_irq) {
 134                disable_irq_nosync(sock->insert_irq);
 135                enable_irq(sock->eject_irq);
 136        } else {
 137                disable_irq_nosync(sock->eject_irq);
 138                enable_irq(sock->insert_irq);
 139        }
 140
 141        pcmcia_parse_events(&sock->socket, SS_DETECT);
 142
 143        return IRQ_HANDLED;
 144}
 145
 146static int db1x_pcmcia_setup_irqs(struct db1x_pcmcia_sock *sock)
 147{
 148        int ret;
 149
 150        if (sock->stschg_irq != -1) {
 151                ret = request_irq(sock->stschg_irq, db1000_pcmcia_stschgirq,
 152                                  0, "pcmcia_stschg", sock);
 153                if (ret)
 154                        return ret;
 155        }
 156
 157        /* Db/Pb1200 have separate per-socket insertion and ejection
 158         * interrupts, which should show edge behaviour but don't.
 159         * So interrupts are disabled until both insertion and
 160         * ejection handler have been registered and the currently
 161         * active one disabled.
 162         */
 163        if (sock->board_type == BOARD_TYPE_DB1200) {
 164                ret = request_irq(sock->insert_irq, db1200_pcmcia_cdirq,
 165                                  IRQF_DISABLED, "pcmcia_insert", sock);
 166                if (ret)
 167                        goto out1;
 168
 169                ret = request_irq(sock->eject_irq, db1200_pcmcia_cdirq,
 170                                  IRQF_DISABLED, "pcmcia_eject", sock);
 171                if (ret) {
 172                        free_irq(sock->insert_irq, sock);
 173                        goto out1;
 174                }
 175
 176                /* enable the currently silent one */
 177                if (db1200_card_inserted(sock))
 178                        enable_irq(sock->eject_irq);
 179                else
 180                        enable_irq(sock->insert_irq);
 181        } else {
 182                /* all other (older) Db1x00 boards use a GPIO to show
 183                 * card detection status:  use both-edge triggers.
 184                 */
 185                set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
 186                ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,
 187                                  0, "pcmcia_carddetect", sock);
 188
 189                if (ret)
 190                        goto out1;
 191        }
 192
 193        return 0;       /* all done */
 194
 195out1:
 196        if (sock->stschg_irq != -1)
 197                free_irq(sock->stschg_irq, sock);
 198
 199        return ret;
 200}
 201
 202static void db1x_pcmcia_free_irqs(struct db1x_pcmcia_sock *sock)
 203{
 204        if (sock->stschg_irq != -1)
 205                free_irq(sock->stschg_irq, sock);
 206
 207        free_irq(sock->insert_irq, sock);
 208        if (sock->eject_irq != -1)
 209                free_irq(sock->eject_irq, sock);
 210}
 211
 212/*
 213 * configure a PCMCIA socket on the Db1x00 series of boards (and
 214 * compatibles).
 215 *
 216 * 2 external registers are involved:
 217 *   pcmcia_status (offset 0x04): bits [0:1/2:3]: read card voltage id
 218 *   pcmcia_control(offset 0x10):
 219 *      bits[0:1] set vcc for card
 220 *      bits[2:3] set vpp for card
 221 *      bit 4:  enable data buffers
 222 *      bit 7:  reset# for card
 223 *      add 8 for second socket.
 224 */
 225static int db1x_pcmcia_configure(struct pcmcia_socket *skt,
 226                                 struct socket_state_t *state)
 227{
 228        struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
 229        unsigned short cr_clr, cr_set;
 230        unsigned int changed;
 231        int v, p, ret;
 232
 233        /* card voltage setup */
 234        cr_clr = (0xf << (sock->nr * 8)); /* clear voltage settings */
 235        cr_set = 0;
 236        v = p = ret = 0;
 237
 238        switch (state->Vcc) {
 239        case 50:
 240                ++v;
 241        case 33:
 242                ++v;
 243        case 0:
 244                break;
 245        default:
 246                printk(KERN_INFO "pcmcia%d unsupported Vcc %d\n",
 247                        sock->nr, state->Vcc);
 248        }
 249
 250        switch (state->Vpp) {
 251        case 12:
 252                ++p;
 253        case 33:
 254        case 50:
 255                ++p;
 256        case 0:
 257                break;
 258        default:
 259                printk(KERN_INFO "pcmcia%d unsupported Vpp %d\n",
 260                        sock->nr, state->Vpp);
 261        }
 262
 263        /* sanity check: Vpp must be 0, 12, or Vcc */
 264        if (((state->Vcc == 33) && (state->Vpp == 50)) ||
 265            ((state->Vcc == 50) && (state->Vpp == 33))) {
 266                printk(KERN_INFO "pcmcia%d bad Vcc/Vpp combo (%d %d)\n",
 267                        sock->nr, state->Vcc, state->Vpp);
 268                v = p = 0;
 269                ret = -EINVAL;
 270        }
 271
 272        /* create new voltage code */
 273        cr_set |= ((v << 2) | p) << (sock->nr * 8);
 274
 275        changed = state->flags ^ sock->old_flags;
 276
 277        if (changed & SS_RESET) {
 278                if (state->flags & SS_RESET) {
 279                        set_stschg(sock, 0);
 280                        /* assert reset, disable io buffers */
 281                        cr_clr |= (1 << (7 + (sock->nr * 8)));
 282                        cr_clr |= (1 << (4 + (sock->nr * 8)));
 283                } else {
 284                        /* de-assert reset, enable io buffers */
 285                        cr_set |= 1 << (7 + (sock->nr * 8));
 286                        cr_set |= 1 << (4 + (sock->nr * 8));
 287                }
 288        }
 289
 290        /* update PCMCIA configuration */
 291        bcsr_mod(BCSR_PCMCIA, cr_clr, cr_set);
 292
 293        sock->old_flags = state->flags;
 294
 295        /* reset was taken away: give card time to initialize properly */
 296        if ((changed & SS_RESET) && !(state->flags & SS_RESET)) {
 297                msleep(500);
 298                set_stschg(sock, 1);
 299        }
 300
 301        return ret;
 302}
 303
 304/* VCC bits at [3:2]/[11:10] */
 305#define GET_VCC(cr, socknr)             \
 306        ((((cr) >> 2) >> ((socknr) * 8)) & 3)
 307
 308/* VS bits at [0:1]/[3:2] */
 309#define GET_VS(sr, socknr)              \
 310        (((sr) >> (2 * (socknr))) & 3)
 311
 312/* reset bits at [7]/[15] */
 313#define GET_RESET(cr, socknr)           \
 314        ((cr) & (1 << (7 + (8 * (socknr)))))
 315
 316static int db1x_pcmcia_get_status(struct pcmcia_socket *skt,
 317                                  unsigned int *value)
 318{
 319        struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
 320        unsigned short cr, sr;
 321        unsigned int status;
 322
 323        status = db1x_card_inserted(sock) ? SS_DETECT : 0;
 324
 325        cr = bcsr_read(BCSR_PCMCIA);
 326        sr = bcsr_read(BCSR_STATUS);
 327
 328        /* PB1100/PB1500: voltage key bits are at [5:4] */
 329        if (sock->board_type == BOARD_TYPE_PB1100)
 330                sr >>= 4;
 331
 332        /* determine card type */
 333        switch (GET_VS(sr, sock->nr)) {
 334        case 0:
 335        case 2:
 336                status |= SS_3VCARD;    /* 3V card */
 337        case 3:
 338                break;                  /* 5V card: set nothing */
 339        default:
 340                status |= SS_XVCARD;    /* treated as unsupported in core */
 341        }
 342
 343        /* if Vcc is not zero, we have applied power to a card */
 344        status |= GET_VCC(cr, sock->nr) ? SS_POWERON : 0;
 345
 346        /* reset de-asserted? then we're ready */
 347        status |= (GET_RESET(cr, sock->nr)) ? SS_READY : SS_RESET;
 348
 349        *value = status;
 350
 351        return 0;
 352}
 353
 354static int db1x_pcmcia_sock_init(struct pcmcia_socket *skt)
 355{
 356        return 0;
 357}
 358
 359static int db1x_pcmcia_sock_suspend(struct pcmcia_socket *skt)
 360{
 361        return 0;
 362}
 363
 364static int au1x00_pcmcia_set_io_map(struct pcmcia_socket *skt,
 365                                    struct pccard_io_map *map)
 366{
 367        struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
 368
 369        map->start = (u32)sock->virt_io;
 370        map->stop = map->start + IO_MAP_SIZE;
 371
 372        return 0;
 373}
 374
 375static int au1x00_pcmcia_set_mem_map(struct pcmcia_socket *skt,
 376                                     struct pccard_mem_map *map)
 377{
 378        struct db1x_pcmcia_sock *sock = to_db1x_socket(skt);
 379
 380        if (map->flags & MAP_ATTRIB)
 381                map->static_start = sock->phys_attr + map->card_start;
 382        else
 383                map->static_start = sock->phys_mem + map->card_start;
 384
 385        return 0;
 386}
 387
 388static struct pccard_operations db1x_pcmcia_operations = {
 389        .init                   = db1x_pcmcia_sock_init,
 390        .suspend                = db1x_pcmcia_sock_suspend,
 391        .get_status             = db1x_pcmcia_get_status,
 392        .set_socket             = db1x_pcmcia_configure,
 393        .set_io_map             = au1x00_pcmcia_set_io_map,
 394        .set_mem_map            = au1x00_pcmcia_set_mem_map,
 395};
 396
 397static int __devinit db1x_pcmcia_socket_probe(struct platform_device *pdev)
 398{
 399        struct db1x_pcmcia_sock *sock;
 400        struct resource *r;
 401        int ret, bid;
 402
 403        sock = kzalloc(sizeof(struct db1x_pcmcia_sock), GFP_KERNEL);
 404        if (!sock)
 405                return -ENOMEM;
 406
 407        sock->nr = pdev->id;
 408
 409        bid = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
 410        switch (bid) {
 411        case BCSR_WHOAMI_PB1500:
 412        case BCSR_WHOAMI_PB1500R2:
 413        case BCSR_WHOAMI_PB1100:
 414                sock->board_type = BOARD_TYPE_PB1100;
 415                break;
 416        case BCSR_WHOAMI_DB1000 ... BCSR_WHOAMI_PB1550_SDR:
 417                sock->board_type = BOARD_TYPE_DEFAULT;
 418                break;
 419        case BCSR_WHOAMI_PB1200 ... BCSR_WHOAMI_DB1200:
 420                sock->board_type = BOARD_TYPE_DB1200;
 421                break;
 422        default:
 423                printk(KERN_INFO "db1xxx-ss: unknown board %d!\n", bid);
 424                ret = -ENODEV;
 425                goto out0;
 426        };
 427
 428        /*
 429         * gather resources necessary and optional nice-to-haves to
 430         * operate a socket:
 431         * This includes IRQs for Carddetection/ejection, the card
 432         *  itself and optional status change detection.
 433         * Also, the memory areas covered by a socket.  For these
 434         *  we require the real 36bit addresses (see the au1000.h
 435         *  header for more information).
 436         */
 437
 438        /* card: irq assigned to the card itself. */
 439        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "card");
 440        sock->card_irq = r ? r->start : 0;
 441
 442        /* insert: irq which triggers on card insertion/ejection */
 443        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "insert");
 444        sock->insert_irq = r ? r->start : -1;
 445
 446        /* stschg: irq which trigger on card status change (optional) */
 447        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "stschg");
 448        sock->stschg_irq = r ? r->start : -1;
 449
 450        /* eject: irq which triggers on ejection (DB1200/PB1200 only) */
 451        r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "eject");
 452        sock->eject_irq = r ? r->start : -1;
 453
 454        ret = -ENODEV;
 455
 456        /* 36bit PCMCIA Attribute area address */
 457        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-attr");
 458        if (!r) {
 459                printk(KERN_ERR "pcmcia%d has no 'pseudo-attr' resource!\n",
 460                        sock->nr);
 461                goto out0;
 462        }
 463        sock->phys_attr = r->start;
 464
 465        /* 36bit PCMCIA Memory area address */
 466        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-mem");
 467        if (!r) {
 468                printk(KERN_ERR "pcmcia%d has no 'pseudo-mem' resource!\n",
 469                        sock->nr);
 470                goto out0;
 471        }
 472        sock->phys_mem = r->start;
 473
 474        /* 36bit PCMCIA IO area address */
 475        r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcmcia-io");
 476        if (!r) {
 477                printk(KERN_ERR "pcmcia%d has no 'pseudo-io' resource!\n",
 478                        sock->nr);
 479                goto out0;
 480        }
 481        sock->phys_io = r->start;
 482
 483        /*
 484         * PCMCIA client drivers use the inb/outb macros to access
 485         * the IO registers.  Since mips_io_port_base is added
 486         * to the access address of the mips implementation of
 487         * inb/outb, we need to subtract it here because we want
 488         * to access the I/O or MEM address directly, without
 489         * going through this "mips_io_port_base" mechanism.
 490         */
 491        sock->virt_io = (void *)(ioremap(sock->phys_io, IO_MAP_SIZE) -
 492                                 mips_io_port_base);
 493
 494        if (!sock->virt_io) {
 495                printk(KERN_ERR "pcmcia%d: cannot remap IO area\n",
 496                        sock->nr);
 497                ret = -ENOMEM;
 498                goto out0;
 499        }
 500
 501        sock->socket.ops        = &db1x_pcmcia_operations;
 502        sock->socket.owner      = THIS_MODULE;
 503        sock->socket.pci_irq    = sock->card_irq;
 504        sock->socket.features   = SS_CAP_STATIC_MAP | SS_CAP_PCCARD;
 505        sock->socket.map_size   = MEM_MAP_SIZE;
 506        sock->socket.io_offset  = (unsigned long)sock->virt_io;
 507        sock->socket.dev.parent = &pdev->dev;
 508        sock->socket.resource_ops = &pccard_static_ops;
 509
 510        platform_set_drvdata(pdev, sock);
 511
 512        ret = db1x_pcmcia_setup_irqs(sock);
 513        if (ret) {
 514                printk(KERN_ERR "pcmcia%d cannot setup interrupts\n",
 515                        sock->nr);
 516                goto out1;
 517        }
 518
 519        set_stschg(sock, 0);
 520
 521        ret = pcmcia_register_socket(&sock->socket);
 522        if (ret) {
 523                printk(KERN_ERR "pcmcia%d failed to register\n", sock->nr);
 524                goto out2;
 525        }
 526
 527        printk(KERN_INFO "Alchemy Db/Pb1xxx pcmcia%d @ io/attr/mem %09llx"
 528                "(%p) %09llx %09llx  card/insert/stschg/eject irqs @ %d "
 529                "%d %d %d\n", sock->nr, sock->phys_io, sock->virt_io,
 530                sock->phys_attr, sock->phys_mem, sock->card_irq,
 531                sock->insert_irq, sock->stschg_irq, sock->eject_irq);
 532
 533        return 0;
 534
 535out2:
 536        db1x_pcmcia_free_irqs(sock);
 537out1:
 538        iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
 539out0:
 540        kfree(sock);
 541        return ret;
 542}
 543
 544static int __devexit db1x_pcmcia_socket_remove(struct platform_device *pdev)
 545{
 546        struct db1x_pcmcia_sock *sock = platform_get_drvdata(pdev);
 547
 548        db1x_pcmcia_free_irqs(sock);
 549        pcmcia_unregister_socket(&sock->socket);
 550        iounmap((void *)(sock->virt_io + (u32)mips_io_port_base));
 551        kfree(sock);
 552
 553        return 0;
 554}
 555
 556static struct platform_driver db1x_pcmcia_socket_driver = {
 557        .driver = {
 558                .name   = "db1xxx_pcmcia",
 559                .owner  = THIS_MODULE,
 560        },
 561        .probe          = db1x_pcmcia_socket_probe,
 562        .remove         = __devexit_p(db1x_pcmcia_socket_remove),
 563};
 564
 565int __init db1x_pcmcia_socket_load(void)
 566{
 567        return platform_driver_register(&db1x_pcmcia_socket_driver);
 568}
 569
 570void  __exit db1x_pcmcia_socket_unload(void)
 571{
 572        platform_driver_unregister(&db1x_pcmcia_socket_driver);
 573}
 574
 575module_init(db1x_pcmcia_socket_load);
 576module_exit(db1x_pcmcia_socket_unload);
 577
 578MODULE_LICENSE("GPL");
 579MODULE_DESCRIPTION("PCMCIA Socket Services for Alchemy Db/Pb1x00 boards");
 580MODULE_AUTHOR("Manuel Lauss");
 581
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.