linux/drivers/pcmcia/tcic.c
<<
>>
Prefs
   1/*======================================================================
   2
   3    Device driver for Databook TCIC-2 PCMCIA controller
   4
   5    tcic.c 1.111 2000/02/15 04:13:12
   6
   7    The contents of this file are subject to the Mozilla Public
   8    License Version 1.1 (the "License"); you may not use this file
   9    except in compliance with the License. You may obtain a copy of
  10    the License at http://www.mozilla.org/MPL/
  11
  12    Software distributed under the License is distributed on an "AS
  13    IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  14    implied. See the License for the specific language governing
  15    rights and limitations under the License.
  16
  17    The initial developer of the original code is David A. Hinds
  18    <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
  19    are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  20
  21    Alternatively, the contents of this file may be used under the
  22    terms of the GNU General Public License version 2 (the "GPL"), in which
  23    case the provisions of the GPL are applicable instead of the
  24    above.  If you wish to allow the use of your version of this file
  25    only under the terms of the GPL and not to allow others to use
  26    your version of this file under the MPL, indicate your decision
  27    by deleting the provisions above and replace them with the notice
  28    and other provisions required by the GPL.  If you do not delete
  29    the provisions above, a recipient may use your version of this
  30    file under either the MPL or the GPL.
  31    
  32======================================================================*/
  33
  34#include <linux/module.h>
  35#include <linux/moduleparam.h>
  36#include <linux/init.h>
  37#include <linux/types.h>
  38#include <linux/fcntl.h>
  39#include <linux/string.h>
  40#include <linux/errno.h>
  41#include <linux/interrupt.h>
  42#include <linux/timer.h>
  43#include <linux/ioport.h>
  44#include <linux/delay.h>
  45#include <linux/workqueue.h>
  46#include <linux/platform_device.h>
  47#include <linux/bitops.h>
  48
  49#include <asm/io.h>
  50
  51#include <pcmcia/ss.h>
  52#include "tcic.h"
  53
  54MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
  55MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
  56MODULE_LICENSE("Dual MPL/GPL");
  57
  58/*====================================================================*/
  59
  60/* Parameters that can be set with 'insmod' */
  61
  62/* The base port address of the TCIC-2 chip */
  63static unsigned long tcic_base = TCIC_BASE;
  64
  65/* Specify a socket number to ignore */
  66static int ignore = -1;
  67
  68/* Probe for safe interrupts? */
  69static int do_scan = 1;
  70
  71/* Bit map of interrupts to choose from */
  72static u_int irq_mask = 0xffff;
  73static int irq_list[16];
  74static unsigned int irq_list_count;
  75
  76/* The card status change interrupt -- 0 means autoselect */
  77static int cs_irq;
  78
  79/* Poll status interval -- 0 means default to interrupt */
  80static int poll_interval;
  81
  82/* Delay for card status double-checking */
  83static int poll_quick = HZ/20;
  84
  85/* CCLK external clock time, in nanoseconds.  70 ns = 14.31818 MHz */
  86static int cycle_time = 70;
  87
  88module_param(tcic_base, ulong, 0444);
  89module_param(ignore, int, 0444);
  90module_param(do_scan, int, 0444);
  91module_param(irq_mask, int, 0444);
  92module_param_array(irq_list, int, &irq_list_count, 0444);
  93module_param(cs_irq, int, 0444);
  94module_param(poll_interval, int, 0444);
  95module_param(poll_quick, int, 0444);
  96module_param(cycle_time, int, 0444);
  97
  98/*====================================================================*/
  99
 100static irqreturn_t tcic_interrupt(int irq, void *dev);
 101static void tcic_timer(u_long data);
 102static struct pccard_operations tcic_operations;
 103
 104struct tcic_socket {
 105    u_short     psock;
 106    u_char      last_sstat;
 107    u_char      id;
 108    struct pcmcia_socket        socket;
 109};
 110
 111static struct timer_list poll_timer;
 112static int tcic_timer_pending;
 113
 114static int sockets;
 115static struct tcic_socket socket_table[2];
 116
 117/*====================================================================*/
 118
 119/* Trick when selecting interrupts: the TCIC sktirq pin is supposed
 120   to map to irq 11, but is coded as 0 or 1 in the irq registers. */
 121#define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
 122
 123#ifdef DEBUG_X
 124static u_char tcic_getb(u_char reg)
 125{
 126    u_char val = inb(tcic_base+reg);
 127    printk(KERN_DEBUG "tcic_getb(%#lx) = %#x\n", tcic_base+reg, val);
 128    return val;
 129}
 130
 131static u_short tcic_getw(u_char reg)
 132{
 133    u_short val = inw(tcic_base+reg);
 134    printk(KERN_DEBUG "tcic_getw(%#lx) = %#x\n", tcic_base+reg, val);
 135    return val;
 136}
 137
 138static void tcic_setb(u_char reg, u_char data)
 139{
 140    printk(KERN_DEBUG "tcic_setb(%#lx, %#x)\n", tcic_base+reg, data);
 141    outb(data, tcic_base+reg);
 142}
 143
 144static void tcic_setw(u_char reg, u_short data)
 145{
 146    printk(KERN_DEBUG "tcic_setw(%#lx, %#x)\n", tcic_base+reg, data);
 147    outw(data, tcic_base+reg);
 148}
 149#else
 150#define tcic_getb(reg) inb(tcic_base+reg)
 151#define tcic_getw(reg) inw(tcic_base+reg)
 152#define tcic_setb(reg, data) outb(data, tcic_base+reg)
 153#define tcic_setw(reg, data) outw(data, tcic_base+reg)
 154#endif
 155
 156static void tcic_setl(u_char reg, u_int data)
 157{
 158#ifdef DEBUG_X
 159    printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
 160#endif
 161    outw(data & 0xffff, tcic_base+reg);
 162    outw(data >> 16, tcic_base+reg+2);
 163}
 164
 165static void tcic_aux_setb(u_short reg, u_char data)
 166{
 167    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
 168    tcic_setb(TCIC_MODE, mode);
 169    tcic_setb(TCIC_AUX, data);
 170}
 171
 172static u_short tcic_aux_getw(u_short reg)
 173{
 174    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
 175    tcic_setb(TCIC_MODE, mode);
 176    return tcic_getw(TCIC_AUX);
 177}
 178
 179static void tcic_aux_setw(u_short reg, u_short data)
 180{
 181    u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
 182    tcic_setb(TCIC_MODE, mode);
 183    tcic_setw(TCIC_AUX, data);
 184}
 185
 186/*====================================================================*/
 187
 188/* Time conversion functions */
 189
 190static int to_cycles(int ns)
 191{
 192    if (ns < 14)
 193        return 0;
 194    else
 195        return 2*(ns-14)/cycle_time;
 196}
 197
 198/*====================================================================*/
 199
 200static volatile u_int irq_hits;
 201
 202static irqreturn_t __init tcic_irq_count(int irq, void *dev)
 203{
 204    irq_hits++;
 205    return IRQ_HANDLED;
 206}
 207
 208static u_int __init try_irq(int irq)
 209{
 210    u_short cfg;
 211
 212    irq_hits = 0;
 213    if (request_irq(irq, tcic_irq_count, 0, "irq scan", tcic_irq_count) != 0)
 214        return -1;
 215    mdelay(10);
 216    if (irq_hits) {
 217        free_irq(irq, tcic_irq_count);
 218        return -1;
 219    }
 220
 221    /* Generate one interrupt */
 222    cfg = TCIC_SYSCFG_AUTOBUSY | 0x0a00;
 223    tcic_aux_setw(TCIC_AUX_SYSCFG, cfg | TCIC_IRQ(irq));
 224    tcic_setb(TCIC_IENA, TCIC_IENA_ERR | TCIC_IENA_CFG_HIGH);
 225    tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM);
 226
 227    udelay(1000);
 228    free_irq(irq, tcic_irq_count);
 229
 230    /* Turn off interrupts */
 231    tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF);
 232    while (tcic_getb(TCIC_ICSR))
 233        tcic_setb(TCIC_ICSR, TCIC_ICSR_JAM);
 234    tcic_aux_setw(TCIC_AUX_SYSCFG, cfg);
 235    
 236    return (irq_hits != 1);
 237}
 238
 239static u_int __init irq_scan(u_int mask0)
 240{
 241    u_int mask1;
 242    int i;
 243
 244#ifdef __alpha__
 245#define PIC 0x4d0
 246    /* Don't probe level-triggered interrupts -- reserved for PCI */
 247    int level_mask = inb_p(PIC) | (inb_p(PIC+1) << 8);
 248    if (level_mask)
 249        mask0 &= ~level_mask;
 250#endif
 251
 252    mask1 = 0;
 253    if (do_scan) {
 254        for (i = 0; i < 16; i++)
 255            if ((mask0 & (1 << i)) && (try_irq(i) == 0))
 256                mask1 |= (1 << i);
 257        for (i = 0; i < 16; i++)
 258            if ((mask1 & (1 << i)) && (try_irq(i) != 0)) {
 259                mask1 ^= (1 << i);
 260            }
 261    }
 262    
 263    if (mask1) {
 264        printk("scanned");
 265    } else {
 266        /* Fallback: just find interrupts that aren't in use */
 267        for (i = 0; i < 16; i++)
 268            if ((mask0 & (1 << i)) &&
 269                (request_irq(i, tcic_irq_count, 0, "x", tcic_irq_count) == 0)) {
 270                mask1 |= (1 << i);
 271                free_irq(i, tcic_irq_count);
 272            }
 273        printk("default");
 274    }
 275    
 276    printk(") = ");
 277    for (i = 0; i < 16; i++)
 278        if (mask1 & (1<<i))
 279            printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
 280    printk(" ");
 281    
 282    return mask1;
 283}
 284
 285/*======================================================================
 286
 287    See if a card is present, powered up, in IO mode, and already
 288    bound to a (non-PCMCIA) Linux driver.
 289
 290    We make an exception for cards that look like serial devices.
 291    
 292======================================================================*/
 293
 294static int __init is_active(int s)
 295{
 296    u_short scf1, ioctl, base, num;
 297    u_char pwr, sstat;
 298    u_int addr;
 299    
 300    tcic_setl(TCIC_ADDR, (s << TCIC_ADDR_SS_SHFT)
 301              | TCIC_ADDR_INDREG | TCIC_SCF1(s));
 302    scf1 = tcic_getw(TCIC_DATA);
 303    pwr = tcic_getb(TCIC_PWR);
 304    sstat = tcic_getb(TCIC_SSTAT);
 305    addr = TCIC_IWIN(s, 0);
 306    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
 307    base = tcic_getw(TCIC_DATA);
 308    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
 309    ioctl = tcic_getw(TCIC_DATA);
 310
 311    if (ioctl & TCIC_ICTL_TINY)
 312        num = 1;
 313    else {
 314        num = (base ^ (base-1));
 315        base = base & (base-1);
 316    }
 317
 318    if ((sstat & TCIC_SSTAT_CD) && (pwr & TCIC_PWR_VCC(s)) &&
 319        (scf1 & TCIC_SCF1_IOSTS) && (ioctl & TCIC_ICTL_ENA) &&
 320        ((base & 0xfeef) != 0x02e8)) {
 321        struct resource *res = request_region(base, num, "tcic-2");
 322        if (!res) /* region is busy */
 323            return 1;
 324        release_region(base, num);
 325    }
 326
 327    return 0;
 328}
 329
 330/*======================================================================
 331
 332    This returns the revision code for the specified socket.
 333    
 334======================================================================*/
 335
 336static int __init get_tcic_id(void)
 337{
 338    u_short id;
 339    
 340    tcic_aux_setw(TCIC_AUX_TEST, TCIC_TEST_DIAG);
 341    id = tcic_aux_getw(TCIC_AUX_ILOCK);
 342    id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
 343    tcic_aux_setw(TCIC_AUX_TEST, 0);
 344    return id;
 345}
 346
 347/*====================================================================*/
 348
 349static struct platform_driver tcic_driver = {
 350        .driver = {
 351                .name = "tcic-pcmcia",
 352                .owner          = THIS_MODULE,
 353        },
 354};
 355
 356static struct platform_device tcic_device = {
 357        .name = "tcic-pcmcia",
 358        .id = 0,
 359};
 360
 361
 362static int __init init_tcic(void)
 363{
 364    int i, sock, ret = 0;
 365    u_int mask, scan;
 366
 367    if (platform_driver_register(&tcic_driver))
 368        return -1;
 369    
 370    printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
 371    sock = 0;
 372
 373    if (!request_region(tcic_base, 16, "tcic-2")) {
 374        printk("could not allocate ports,\n ");
 375        platform_driver_unregister(&tcic_driver);
 376        return -ENODEV;
 377    }
 378    else {
 379        tcic_setw(TCIC_ADDR, 0);
 380        if (tcic_getw(TCIC_ADDR) == 0) {
 381            tcic_setw(TCIC_ADDR, 0xc3a5);
 382            if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
 383        }
 384        if (sock == 0) {
 385            /* See if resetting the controller does any good */
 386            tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
 387            tcic_setb(TCIC_SCTRL, 0);
 388            tcic_setw(TCIC_ADDR, 0);
 389            if (tcic_getw(TCIC_ADDR) == 0) {
 390                tcic_setw(TCIC_ADDR, 0xc3a5);
 391                if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
 392            }
 393        }
 394    }
 395    if (sock == 0) {
 396        printk("not found.\n");
 397        release_region(tcic_base, 16);
 398        platform_driver_unregister(&tcic_driver);
 399        return -ENODEV;
 400    }
 401
 402    sockets = 0;
 403    for (i = 0; i < sock; i++) {
 404        if ((i == ignore) || is_active(i)) continue;
 405        socket_table[sockets].psock = i;
 406        socket_table[sockets].id = get_tcic_id();
 407
 408        socket_table[sockets].socket.owner = THIS_MODULE;
 409        /* only 16-bit cards, memory windows must be size-aligned */
 410        /* No PCI or CardBus support */
 411        socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
 412        /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
 413        socket_table[sockets].socket.irq_mask = 0x4cf8;
 414        /* 4K minimum window size */
 415        socket_table[sockets].socket.map_size = 0x1000;         
 416        sockets++;
 417    }
 418
 419    switch (socket_table[0].id) {
 420    case TCIC_ID_DB86082:
 421        printk("DB86082"); break;
 422    case TCIC_ID_DB86082A:
 423        printk("DB86082A"); break;
 424    case TCIC_ID_DB86084:
 425        printk("DB86084"); break;
 426    case TCIC_ID_DB86084A:
 427        printk("DB86084A"); break;
 428    case TCIC_ID_DB86072:
 429        printk("DB86072"); break;
 430    case TCIC_ID_DB86184:
 431        printk("DB86184"); break;
 432    case TCIC_ID_DB86082B:
 433        printk("DB86082B"); break;
 434    default:
 435        printk("Unknown ID 0x%02x", socket_table[0].id);
 436    }
 437    
 438    /* Set up polling */
 439    poll_timer.function = &tcic_timer;
 440    poll_timer.data = 0;
 441    init_timer(&poll_timer);
 442
 443    /* Build interrupt mask */
 444    printk(KERN_CONT ", %d sockets\n", sockets);
 445    printk(KERN_INFO "  irq list (");
 446    if (irq_list_count == 0)
 447        mask = irq_mask;
 448    else
 449        for (i = mask = 0; i < irq_list_count; i++)
 450            mask |= (1<<irq_list[i]);
 451
 452    /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
 453    mask &= 0x4cf8;
 454    /* Scan interrupts */
 455    mask = irq_scan(mask);
 456    for (i=0;i<sockets;i++)
 457            socket_table[i].socket.irq_mask = mask;
 458    
 459    /* Check for only two interrupts available */
 460    scan = (mask & (mask-1));
 461    if (((scan & (scan-1)) == 0) && (poll_interval == 0))
 462        poll_interval = HZ;
 463    
 464    if (poll_interval == 0) {
 465        /* Avoid irq 12 unless it is explicitly requested */
 466        u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
 467        for (i = 15; i > 0; i--)
 468            if ((cs_mask & (1 << i)) &&
 469                (request_irq(i, tcic_interrupt, 0, "tcic",
 470                             tcic_interrupt) == 0))
 471                break;
 472        cs_irq = i;
 473        if (cs_irq == 0) poll_interval = HZ;
 474    }
 475    
 476    if (socket_table[0].socket.irq_mask & (1 << 11))
 477        printk("sktirq is irq 11, ");
 478    if (cs_irq != 0)
 479        printk("status change on irq %d\n", cs_irq);
 480    else
 481        printk("polled status, interval = %d ms\n",
 482               poll_interval * 1000 / HZ);
 483    
 484    for (i = 0; i < sockets; i++) {
 485        tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
 486        socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
 487    }
 488    
 489    /* jump start interrupt handler, if needed */
 490    tcic_interrupt(0, NULL);
 491
 492    platform_device_register(&tcic_device);
 493
 494    for (i = 0; i < sockets; i++) {
 495            socket_table[i].socket.ops = &tcic_operations;
 496            socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
 497            socket_table[i].socket.dev.parent = &tcic_device.dev;
 498            ret = pcmcia_register_socket(&socket_table[i].socket);
 499            if (ret && i)
 500                    pcmcia_unregister_socket(&socket_table[0].socket);
 501    }
 502    
 503    return ret;
 504
 505    return 0;
 506    
 507} /* init_tcic */
 508
 509/*====================================================================*/
 510
 511static void __exit exit_tcic(void)
 512{
 513    int i;
 514
 515    del_timer_sync(&poll_timer);
 516    if (cs_irq != 0) {
 517        tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
 518        free_irq(cs_irq, tcic_interrupt);
 519    }
 520    release_region(tcic_base, 16);
 521
 522    for (i = 0; i < sockets; i++) {
 523            pcmcia_unregister_socket(&socket_table[i].socket);      
 524    }
 525
 526    platform_device_unregister(&tcic_device);
 527    platform_driver_unregister(&tcic_driver);
 528} /* exit_tcic */
 529
 530/*====================================================================*/
 531
 532static irqreturn_t tcic_interrupt(int irq, void *dev)
 533{
 534    int i, quick = 0;
 535    u_char latch, sstat;
 536    u_short psock;
 537    u_int events;
 538    static volatile int active = 0;
 539
 540    if (active) {
 541        printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
 542        return IRQ_NONE;
 543    } else
 544        active = 1;
 545
 546    pr_debug("tcic_interrupt()\n");
 547    
 548    for (i = 0; i < sockets; i++) {
 549        psock = socket_table[i].psock;
 550        tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
 551                  | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
 552        sstat = tcic_getb(TCIC_SSTAT);
 553        latch = sstat ^ socket_table[psock].last_sstat;
 554        socket_table[i].last_sstat = sstat;
 555        if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
 556            tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
 557            quick = 1;
 558        }
 559        if (latch == 0)
 560            continue;
 561        events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
 562        events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
 563        if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
 564            events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
 565        } else {
 566            events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
 567            events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
 568            events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
 569        }
 570        if (events) {
 571                pcmcia_parse_events(&socket_table[i].socket, events);
 572        }
 573    }
 574
 575    /* Schedule next poll, if needed */
 576    if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
 577        poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
 578        add_timer(&poll_timer);
 579        tcic_timer_pending = 1;
 580    }
 581    active = 0;
 582    
 583    pr_debug("interrupt done\n");
 584    return IRQ_HANDLED;
 585} /* tcic_interrupt */
 586
 587static void tcic_timer(u_long data)
 588{
 589    pr_debug("tcic_timer()\n");
 590    tcic_timer_pending = 0;
 591    tcic_interrupt(0, NULL);
 592} /* tcic_timer */
 593
 594/*====================================================================*/
 595
 596static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
 597{
 598    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 599    u_char reg;
 600
 601    tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
 602              | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
 603    reg = tcic_getb(TCIC_SSTAT);
 604    *value  = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;
 605    *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
 606    if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
 607        *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
 608    } else {
 609        *value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;
 610        *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
 611        *value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
 612    }
 613    reg = tcic_getb(TCIC_PWR);
 614    if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
 615        *value |= SS_POWERON;
 616    dev_dbg(&sock->dev, "GetStatus(%d) = %#2.2x\n", psock, *value);
 617    return 0;
 618} /* tcic_get_status */
 619
 620/*====================================================================*/
 621
 622static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 623{
 624    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 625    u_char reg;
 626    u_short scf1, scf2;
 627
 628    dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 629          "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
 630          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
 631    tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
 632
 633    reg = tcic_getb(TCIC_PWR);
 634    reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
 635
 636    if (state->Vcc == 50) {
 637        switch (state->Vpp) {
 638        case 0:   reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
 639        case 50:  reg |= TCIC_PWR_VCC(psock); break;
 640        case 120: reg |= TCIC_PWR_VPP(psock); break;
 641        default:  return -EINVAL;
 642        }
 643    } else if (state->Vcc != 0)
 644        return -EINVAL;
 645
 646    if (reg != tcic_getb(TCIC_PWR))
 647        tcic_setb(TCIC_PWR, reg);
 648
 649    reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
 650    if (state->flags & SS_OUTPUT_ENA) {
 651        tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
 652        reg |= TCIC_ILOCK_CRESENA;
 653    } else
 654        tcic_setb(TCIC_SCTRL, 0);
 655    if (state->flags & SS_RESET)
 656        reg |= TCIC_ILOCK_CRESET;
 657    tcic_aux_setb(TCIC_AUX_ILOCK, reg);
 658    
 659    tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
 660    scf1 = TCIC_SCF1_FINPACK;
 661    scf1 |= TCIC_IRQ(state->io_irq);
 662    if (state->flags & SS_IOCARD) {
 663        scf1 |= TCIC_SCF1_IOSTS;
 664        if (state->flags & SS_SPKR_ENA)
 665            scf1 |= TCIC_SCF1_SPKR;
 666        if (state->flags & SS_DMA_MODE)
 667            scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
 668    }
 669    tcic_setw(TCIC_DATA, scf1);
 670
 671    /* Some general setup stuff, and configure status interrupt */
 672    reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
 673    tcic_aux_setb(TCIC_AUX_WCTL, reg);
 674    tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
 675                  TCIC_IRQ(cs_irq));
 676    
 677    /* Card status change interrupt mask */
 678    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
 679    scf2 = TCIC_SCF2_MALL;
 680    if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
 681    if (state->flags & SS_IOCARD) {
 682        if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
 683    } else {
 684        if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
 685        if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
 686        if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
 687    }
 688    tcic_setw(TCIC_DATA, scf2);
 689    /* For the ISA bus, the irq should be active-high totem-pole */
 690    tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
 691
 692    return 0;
 693} /* tcic_set_socket */
 694  
 695/*====================================================================*/
 696
 697static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 698{
 699    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 700    u_int addr;
 701    u_short base, len, ioctl;
 702    
 703    dev_dbg(&sock->dev, "SetIOMap(%d, %d, %#2.2x, %d ns, "
 704          "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,
 705          (unsigned long long)io->start, (unsigned long long)io->stop);
 706    if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
 707        (io->stop < io->start)) return -EINVAL;
 708    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
 709    addr = TCIC_IWIN(psock, io->map);
 710
 711    base = io->start; len = io->stop - io->start;
 712    /* Check to see that len+1 is power of two, etc */
 713    if ((len & (len+1)) || (base & len)) return -EINVAL;
 714    base |= (len+1)>>1;
 715    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
 716    tcic_setw(TCIC_DATA, base);
 717    
 718    ioctl  = (psock << TCIC_ICTL_SS_SHFT);
 719    ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
 720    ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
 721    ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
 722    if (!(io->flags & MAP_AUTOSZ)) {
 723        ioctl |= TCIC_ICTL_QUIET;
 724        ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
 725    }
 726    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
 727    tcic_setw(TCIC_DATA, ioctl);
 728    
 729    return 0;
 730} /* tcic_set_io_map */
 731
 732/*====================================================================*/
 733
 734static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 735{
 736    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 737    u_short addr, ctl;
 738    u_long base, len, mmap;
 739
 740    dev_dbg(&sock->dev, "SetMemMap(%d, %d, %#2.2x, %d ns, "
 741          "%#llx-%#llx, %#x)\n", psock, mem->map, mem->flags,
 742          mem->speed, (unsigned long long)mem->res->start,
 743          (unsigned long long)mem->res->end, mem->card_start);
 744    if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
 745        (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
 746        (mem->res->start > mem->res->end) || (mem->speed > 1000))
 747        return -EINVAL;
 748    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
 749    addr = TCIC_MWIN(psock, mem->map);
 750
 751    base = mem->res->start; len = mem->res->end - mem->res->start;
 752    if ((len & (len+1)) || (base & len)) return -EINVAL;
 753    if (len == 0x0fff)
 754        base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
 755    else
 756        base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
 757    tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
 758    tcic_setw(TCIC_DATA, base);
 759    
 760    mmap = mem->card_start - mem->res->start;
 761    mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
 762    if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
 763    tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
 764    tcic_setw(TCIC_DATA, mmap);
 765
 766    ctl  = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
 767    ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
 768    ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
 769    ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
 770    ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
 771    tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
 772    tcic_setw(TCIC_DATA, ctl);
 773    
 774    return 0;
 775} /* tcic_set_mem_map */
 776
 777/*====================================================================*/
 778
 779static int tcic_init(struct pcmcia_socket *s)
 780{
 781        int i;
 782        struct resource res = { .start = 0, .end = 0x1000 };
 783        pccard_io_map io = { 0, 0, 0, 0, 1 };
 784        pccard_mem_map mem = { .res = &res, };
 785
 786        for (i = 0; i < 2; i++) {
 787                io.map = i;
 788                tcic_set_io_map(s, &io);
 789        }
 790        for (i = 0; i < 5; i++) {
 791                mem.map = i;
 792                tcic_set_mem_map(s, &mem);
 793        }
 794        return 0;
 795}
 796
 797static struct pccard_operations tcic_operations = {
 798        .init              = tcic_init,
 799        .get_status        = tcic_get_status,
 800        .set_socket        = tcic_set_socket,
 801        .set_io_map        = tcic_set_io_map,
 802        .set_mem_map       = tcic_set_mem_map,
 803};
 804
 805/*====================================================================*/
 806
 807module_init(init_tcic);
 808module_exit(exit_tcic);
 809
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.