cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tcic.c (23935B)


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