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