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_hw(tcic_base, ulong, ioport, 0444);
  89module_param(ignore, int, 0444);
  90module_param(do_scan, int, 0444);
  91module_param_hw(irq_mask, int, other, 0444);
  92module_param_hw_array(irq_list, int, irq, &irq_list_count, 0444);
  93module_param_hw(cs_irq, int, irq, 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        },
 353};
 354
 355static struct platform_device tcic_device = {
 356        .name = "tcic-pcmcia",
 357        .id = 0,
 358};
 359
 360
 361static int __init init_tcic(void)
 362{
 363    int i, sock, ret = 0;
 364    u_int mask, scan;
 365
 366    if (platform_driver_register(&tcic_driver))
 367        return -1;
 368    
 369    printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
 370    sock = 0;
 371
 372    if (!request_region(tcic_base, 16, "tcic-2")) {
 373        printk("could not allocate ports,\n ");
 374        platform_driver_unregister(&tcic_driver);
 375        return -ENODEV;
 376    }
 377    else {
 378        tcic_setw(TCIC_ADDR, 0);
 379        if (tcic_getw(TCIC_ADDR) == 0) {
 380            tcic_setw(TCIC_ADDR, 0xc3a5);
 381            if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
 382        }
 383        if (sock == 0) {
 384            /* See if resetting the controller does any good */
 385            tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
 386            tcic_setb(TCIC_SCTRL, 0);
 387            tcic_setw(TCIC_ADDR, 0);
 388            if (tcic_getw(TCIC_ADDR) == 0) {
 389                tcic_setw(TCIC_ADDR, 0xc3a5);
 390                if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
 391            }
 392        }
 393    }
 394    if (sock == 0) {
 395        printk("not found.\n");
 396        release_region(tcic_base, 16);
 397        platform_driver_unregister(&tcic_driver);
 398        return -ENODEV;
 399    }
 400
 401    sockets = 0;
 402    for (i = 0; i < sock; i++) {
 403        if ((i == ignore) || is_active(i)) continue;
 404        socket_table[sockets].psock = i;
 405        socket_table[sockets].id = get_tcic_id();
 406
 407        socket_table[sockets].socket.owner = THIS_MODULE;
 408        /* only 16-bit cards, memory windows must be size-aligned */
 409        /* No PCI or CardBus support */
 410        socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
 411        /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
 412        socket_table[sockets].socket.irq_mask = 0x4cf8;
 413        /* 4K minimum window size */
 414        socket_table[sockets].socket.map_size = 0x1000;         
 415        sockets++;
 416    }
 417
 418    switch (socket_table[0].id) {
 419    case TCIC_ID_DB86082:
 420        printk("DB86082"); break;
 421    case TCIC_ID_DB86082A:
 422        printk("DB86082A"); break;
 423    case TCIC_ID_DB86084:
 424        printk("DB86084"); break;
 425    case TCIC_ID_DB86084A:
 426        printk("DB86084A"); break;
 427    case TCIC_ID_DB86072:
 428        printk("DB86072"); break;
 429    case TCIC_ID_DB86184:
 430        printk("DB86184"); break;
 431    case TCIC_ID_DB86082B:
 432        printk("DB86082B"); break;
 433    default:
 434        printk("Unknown ID 0x%02x", socket_table[0].id);
 435    }
 436    
 437    /* Set up polling */
 438    poll_timer.function = &tcic_timer;
 439    poll_timer.data = 0;
 440    init_timer(&poll_timer);
 441
 442    /* Build interrupt mask */
 443    printk(KERN_CONT ", %d sockets\n", sockets);
 444    printk(KERN_INFO "  irq list (");
 445    if (irq_list_count == 0)
 446        mask = irq_mask;
 447    else
 448        for (i = mask = 0; i < irq_list_count; i++)
 449            mask |= (1<<irq_list[i]);
 450
 451    /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
 452    mask &= 0x4cf8;
 453    /* Scan interrupts */
 454    mask = irq_scan(mask);
 455    for (i=0;i<sockets;i++)
 456            socket_table[i].socket.irq_mask = mask;
 457    
 458    /* Check for only two interrupts available */
 459    scan = (mask & (mask-1));
 460    if (((scan & (scan-1)) == 0) && (poll_interval == 0))
 461        poll_interval = HZ;
 462    
 463    if (poll_interval == 0) {
 464        /* Avoid irq 12 unless it is explicitly requested */
 465        u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
 466        for (i = 15; i > 0; i--)
 467            if ((cs_mask & (1 << i)) &&
 468                (request_irq(i, tcic_interrupt, 0, "tcic",
 469                             tcic_interrupt) == 0))
 470                break;
 471        cs_irq = i;
 472        if (cs_irq == 0) poll_interval = HZ;
 473    }
 474    
 475    if (socket_table[0].socket.irq_mask & (1 << 11))
 476        printk("sktirq is irq 11, ");
 477    if (cs_irq != 0)
 478        printk("status change on irq %d\n", cs_irq);
 479    else
 480        printk("polled status, interval = %d ms\n",
 481               poll_interval * 1000 / HZ);
 482    
 483    for (i = 0; i < sockets; i++) {
 484        tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
 485        socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
 486    }
 487    
 488    /* jump start interrupt handler, if needed */
 489    tcic_interrupt(0, NULL);
 490
 491    platform_device_register(&tcic_device);
 492
 493    for (i = 0; i < sockets; i++) {
 494            socket_table[i].socket.ops = &tcic_operations;
 495            socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
 496            socket_table[i].socket.dev.parent = &tcic_device.dev;
 497            ret = pcmcia_register_socket(&socket_table[i].socket);
 498            if (ret && i)
 499                    pcmcia_unregister_socket(&socket_table[0].socket);
 500    }
 501    
 502    return ret;
 503
 504    return 0;
 505    
 506} /* init_tcic */
 507
 508/*====================================================================*/
 509
 510static void __exit exit_tcic(void)
 511{
 512    int i;
 513
 514    del_timer_sync(&poll_timer);
 515    if (cs_irq != 0) {
 516        tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
 517        free_irq(cs_irq, tcic_interrupt);
 518    }
 519    release_region(tcic_base, 16);
 520
 521    for (i = 0; i < sockets; i++) {
 522            pcmcia_unregister_socket(&socket_table[i].socket);      
 523    }
 524
 525    platform_device_unregister(&tcic_device);
 526    platform_driver_unregister(&tcic_driver);
 527} /* exit_tcic */
 528
 529/*====================================================================*/
 530
 531static irqreturn_t tcic_interrupt(int irq, void *dev)
 532{
 533    int i, quick = 0;
 534    u_char latch, sstat;
 535    u_short psock;
 536    u_int events;
 537    static volatile int active = 0;
 538
 539    if (active) {
 540        printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
 541        return IRQ_NONE;
 542    } else
 543        active = 1;
 544
 545    pr_debug("tcic_interrupt()\n");
 546    
 547    for (i = 0; i < sockets; i++) {
 548        psock = socket_table[i].psock;
 549        tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
 550                  | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
 551        sstat = tcic_getb(TCIC_SSTAT);
 552        latch = sstat ^ socket_table[psock].last_sstat;
 553        socket_table[i].last_sstat = sstat;
 554        if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
 555            tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
 556            quick = 1;
 557        }
 558        if (latch == 0)
 559            continue;
 560        events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
 561        events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
 562        if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
 563            events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
 564        } else {
 565            events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
 566            events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
 567            events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
 568        }
 569        if (events) {
 570                pcmcia_parse_events(&socket_table[i].socket, events);
 571        }
 572    }
 573
 574    /* Schedule next poll, if needed */
 575    if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
 576        poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
 577        add_timer(&poll_timer);
 578        tcic_timer_pending = 1;
 579    }
 580    active = 0;
 581    
 582    pr_debug("interrupt done\n");
 583    return IRQ_HANDLED;
 584} /* tcic_interrupt */
 585
 586static void tcic_timer(u_long data)
 587{
 588    pr_debug("tcic_timer()\n");
 589    tcic_timer_pending = 0;
 590    tcic_interrupt(0, NULL);
 591} /* tcic_timer */
 592
 593/*====================================================================*/
 594
 595static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
 596{
 597    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 598    u_char reg;
 599
 600    tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
 601              | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
 602    reg = tcic_getb(TCIC_SSTAT);
 603    *value  = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;
 604    *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
 605    if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
 606        *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
 607    } else {
 608        *value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;
 609        *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
 610        *value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
 611    }
 612    reg = tcic_getb(TCIC_PWR);
 613    if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
 614        *value |= SS_POWERON;
 615    dev_dbg(&sock->dev, "GetStatus(%d) = %#2.2x\n", psock, *value);
 616    return 0;
 617} /* tcic_get_status */
 618
 619/*====================================================================*/
 620
 621static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
 622{
 623    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 624    u_char reg;
 625    u_short scf1, scf2;
 626
 627    dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
 628          "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
 629          state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
 630    tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
 631
 632    reg = tcic_getb(TCIC_PWR);
 633    reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
 634
 635    if (state->Vcc == 50) {
 636        switch (state->Vpp) {
 637        case 0:   reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
 638        case 50:  reg |= TCIC_PWR_VCC(psock); break;
 639        case 120: reg |= TCIC_PWR_VPP(psock); break;
 640        default:  return -EINVAL;
 641        }
 642    } else if (state->Vcc != 0)
 643        return -EINVAL;
 644
 645    if (reg != tcic_getb(TCIC_PWR))
 646        tcic_setb(TCIC_PWR, reg);
 647
 648    reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
 649    if (state->flags & SS_OUTPUT_ENA) {
 650        tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
 651        reg |= TCIC_ILOCK_CRESENA;
 652    } else
 653        tcic_setb(TCIC_SCTRL, 0);
 654    if (state->flags & SS_RESET)
 655        reg |= TCIC_ILOCK_CRESET;
 656    tcic_aux_setb(TCIC_AUX_ILOCK, reg);
 657    
 658    tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
 659    scf1 = TCIC_SCF1_FINPACK;
 660    scf1 |= TCIC_IRQ(state->io_irq);
 661    if (state->flags & SS_IOCARD) {
 662        scf1 |= TCIC_SCF1_IOSTS;
 663        if (state->flags & SS_SPKR_ENA)
 664            scf1 |= TCIC_SCF1_SPKR;
 665        if (state->flags & SS_DMA_MODE)
 666            scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
 667    }
 668    tcic_setw(TCIC_DATA, scf1);
 669
 670    /* Some general setup stuff, and configure status interrupt */
 671    reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
 672    tcic_aux_setb(TCIC_AUX_WCTL, reg);
 673    tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
 674                  TCIC_IRQ(cs_irq));
 675    
 676    /* Card status change interrupt mask */
 677    tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
 678    scf2 = TCIC_SCF2_MALL;
 679    if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
 680    if (state->flags & SS_IOCARD) {
 681        if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
 682    } else {
 683        if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
 684        if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
 685        if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
 686    }
 687    tcic_setw(TCIC_DATA, scf2);
 688    /* For the ISA bus, the irq should be active-high totem-pole */
 689    tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
 690
 691    return 0;
 692} /* tcic_set_socket */
 693  
 694/*====================================================================*/
 695
 696static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
 697{
 698    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 699    u_int addr;
 700    u_short base, len, ioctl;
 701    
 702    dev_dbg(&sock->dev, "SetIOMap(%d, %d, %#2.2x, %d ns, "
 703          "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,
 704          (unsigned long long)io->start, (unsigned long long)io->stop);
 705    if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
 706        (io->stop < io->start)) return -EINVAL;
 707    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
 708    addr = TCIC_IWIN(psock, io->map);
 709
 710    base = io->start; len = io->stop - io->start;
 711    /* Check to see that len+1 is power of two, etc */
 712    if ((len & (len+1)) || (base & len)) return -EINVAL;
 713    base |= (len+1)>>1;
 714    tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
 715    tcic_setw(TCIC_DATA, base);
 716    
 717    ioctl  = (psock << TCIC_ICTL_SS_SHFT);
 718    ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
 719    ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
 720    ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
 721    if (!(io->flags & MAP_AUTOSZ)) {
 722        ioctl |= TCIC_ICTL_QUIET;
 723        ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
 724    }
 725    tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
 726    tcic_setw(TCIC_DATA, ioctl);
 727    
 728    return 0;
 729} /* tcic_set_io_map */
 730
 731/*====================================================================*/
 732
 733static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
 734{
 735    u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
 736    u_short addr, ctl;
 737    u_long base, len, mmap;
 738
 739    dev_dbg(&sock->dev, "SetMemMap(%d, %d, %#2.2x, %d ns, "
 740          "%#llx-%#llx, %#x)\n", psock, mem->map, mem->flags,
 741          mem->speed, (unsigned long long)mem->res->start,
 742          (unsigned long long)mem->res->end, mem->card_start);
 743    if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
 744        (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
 745        (mem->res->start > mem->res->end) || (mem->speed > 1000))
 746        return -EINVAL;
 747    tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
 748    addr = TCIC_MWIN(psock, mem->map);
 749
 750    base = mem->res->start; len = mem->res->end - mem->res->start;
 751    if ((len & (len+1)) || (base & len)) return -EINVAL;
 752    if (len == 0x0fff)
 753        base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
 754    else
 755        base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
 756    tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
 757    tcic_setw(TCIC_DATA, base);
 758    
 759    mmap = mem->card_start - mem->res->start;
 760    mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
 761    if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
 762    tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
 763    tcic_setw(TCIC_DATA, mmap);
 764
 765    ctl  = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
 766    ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
 767    ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
 768    ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
 769    ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
 770    tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
 771    tcic_setw(TCIC_DATA, ctl);
 772    
 773    return 0;
 774} /* tcic_set_mem_map */
 775
 776/*====================================================================*/
 777
 778static int tcic_init(struct pcmcia_socket *s)
 779{
 780        int i;
 781        struct resource res = { .start = 0, .end = 0x1000 };
 782        pccard_io_map io = { 0, 0, 0, 0, 1 };
 783        pccard_mem_map mem = { .res = &res, };
 784
 785        for (i = 0; i < 2; i++) {
 786                io.map = i;
 787                tcic_set_io_map(s, &io);
 788        }
 789        for (i = 0; i < 5; i++) {
 790                mem.map = i;
 791                tcic_set_mem_map(s, &mem);
 792        }
 793        return 0;
 794}
 795
 796static struct pccard_operations tcic_operations = {
 797        .init              = tcic_init,
 798        .get_status        = tcic_get_status,
 799        .set_socket        = tcic_set_socket,
 800        .set_io_map        = tcic_set_io_map,
 801        .set_mem_map       = tcic_set_mem_map,
 802};
 803
 804/*====================================================================*/
 805
 806module_init(init_tcic);
 807module_exit(exit_tcic);
 808