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