Back to home page

OSCL-LXR

 
 

    


0001 /*======================================================================
0002 
0003     Device driver for Databook TCIC-2 PCMCIA controller
0004 
0005     tcic.c 1.111 2000/02/15 04:13:12
0006 
0007     The contents of this file are subject to the Mozilla Public
0008     License Version 1.1 (the "License"); you may not use this file
0009     except in compliance with the License. You may obtain a copy of
0010     the License at http://www.mozilla.org/MPL/
0011 
0012     Software distributed under the License is distributed on an "AS
0013     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
0014     implied. See the License for the specific language governing
0015     rights and limitations under the License.
0016 
0017     The initial developer of the original code is David A. Hinds
0018     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
0019     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
0020 
0021     Alternatively, the contents of this file may be used under the
0022     terms of the GNU General Public License version 2 (the "GPL"), in which
0023     case the provisions of the GPL are applicable instead of the
0024     above.  If you wish to allow the use of your version of this file
0025     only under the terms of the GPL and not to allow others to use
0026     your version of this file under the MPL, indicate your decision
0027     by deleting the provisions above and replace them with the notice
0028     and other provisions required by the GPL.  If you do not delete
0029     the provisions above, a recipient may use your version of this
0030     file under either the MPL or the GPL.
0031     
0032 ======================================================================*/
0033 
0034 #include <linux/module.h>
0035 #include <linux/moduleparam.h>
0036 #include <linux/init.h>
0037 #include <linux/types.h>
0038 #include <linux/fcntl.h>
0039 #include <linux/string.h>
0040 #include <linux/errno.h>
0041 #include <linux/interrupt.h>
0042 #include <linux/timer.h>
0043 #include <linux/ioport.h>
0044 #include <linux/delay.h>
0045 #include <linux/workqueue.h>
0046 #include <linux/platform_device.h>
0047 #include <linux/bitops.h>
0048 
0049 #include <asm/io.h>
0050 
0051 #include <pcmcia/ss.h>
0052 #include "tcic.h"
0053 
0054 MODULE_AUTHOR("David Hinds <dahinds@users.sourceforge.net>");
0055 MODULE_DESCRIPTION("Databook TCIC-2 PCMCIA socket driver");
0056 MODULE_LICENSE("Dual MPL/GPL");
0057 
0058 /*====================================================================*/
0059 
0060 /* Parameters that can be set with 'insmod' */
0061 
0062 /* The base port address of the TCIC-2 chip */
0063 static unsigned long tcic_base = TCIC_BASE;
0064 
0065 /* Specify a socket number to ignore */
0066 static int ignore = -1;
0067 
0068 /* Probe for safe interrupts? */
0069 static int do_scan = 1;
0070 
0071 /* Bit map of interrupts to choose from */
0072 static u_int irq_mask = 0xffff;
0073 static int irq_list[16];
0074 static unsigned int irq_list_count;
0075 
0076 /* The card status change interrupt -- 0 means autoselect */
0077 static int cs_irq;
0078 
0079 /* Poll status interval -- 0 means default to interrupt */
0080 static int poll_interval;
0081 
0082 /* Delay for card status double-checking */
0083 static int poll_quick = HZ/20;
0084 
0085 /* CCLK external clock time, in nanoseconds.  70 ns = 14.31818 MHz */
0086 static int cycle_time = 70;
0087 
0088 module_param_hw(tcic_base, ulong, ioport, 0444);
0089 module_param(ignore, int, 0444);
0090 module_param(do_scan, int, 0444);
0091 module_param_hw(irq_mask, int, other, 0444);
0092 module_param_hw_array(irq_list, int, irq, &irq_list_count, 0444);
0093 module_param_hw(cs_irq, int, irq, 0444);
0094 module_param(poll_interval, int, 0444);
0095 module_param(poll_quick, int, 0444);
0096 module_param(cycle_time, int, 0444);
0097 
0098 /*====================================================================*/
0099 
0100 static irqreturn_t tcic_interrupt(int irq, void *dev);
0101 static void tcic_timer(struct timer_list *unused);
0102 static struct pccard_operations tcic_operations;
0103 
0104 struct tcic_socket {
0105     u_short psock;
0106     u_char  last_sstat;
0107     u_char  id;
0108     struct pcmcia_socket    socket;
0109 };
0110 
0111 static struct timer_list poll_timer;
0112 static int tcic_timer_pending;
0113 
0114 static int sockets;
0115 static struct tcic_socket socket_table[2];
0116 
0117 /*====================================================================*/
0118 
0119 /* Trick when selecting interrupts: the TCIC sktirq pin is supposed
0120    to map to irq 11, but is coded as 0 or 1 in the irq registers. */
0121 #define TCIC_IRQ(x) ((x) ? (((x) == 11) ? 1 : (x)) : 15)
0122 
0123 #ifdef DEBUG_X
0124 static u_char tcic_getb(u_char reg)
0125 {
0126     u_char val = inb(tcic_base+reg);
0127     printk(KERN_DEBUG "tcic_getb(%#lx) = %#x\n", tcic_base+reg, val);
0128     return val;
0129 }
0130 
0131 static u_short tcic_getw(u_char reg)
0132 {
0133     u_short val = inw(tcic_base+reg);
0134     printk(KERN_DEBUG "tcic_getw(%#lx) = %#x\n", tcic_base+reg, val);
0135     return val;
0136 }
0137 
0138 static void tcic_setb(u_char reg, u_char data)
0139 {
0140     printk(KERN_DEBUG "tcic_setb(%#lx, %#x)\n", tcic_base+reg, data);
0141     outb(data, tcic_base+reg);
0142 }
0143 
0144 static void tcic_setw(u_char reg, u_short data)
0145 {
0146     printk(KERN_DEBUG "tcic_setw(%#lx, %#x)\n", tcic_base+reg, data);
0147     outw(data, tcic_base+reg);
0148 }
0149 #else
0150 #define tcic_getb(reg) inb(tcic_base+reg)
0151 #define tcic_getw(reg) inw(tcic_base+reg)
0152 #define tcic_setb(reg, data) outb(data, tcic_base+reg)
0153 #define tcic_setw(reg, data) outw(data, tcic_base+reg)
0154 #endif
0155 
0156 static void tcic_setl(u_char reg, u_int data)
0157 {
0158 #ifdef DEBUG_X
0159     printk(KERN_DEBUG "tcic_setl(%#x, %#lx)\n", tcic_base+reg, data);
0160 #endif
0161     outw(data & 0xffff, tcic_base+reg);
0162     outw(data >> 16, tcic_base+reg+2);
0163 }
0164 
0165 static void tcic_aux_setb(u_short reg, u_char data)
0166 {
0167     u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
0168     tcic_setb(TCIC_MODE, mode);
0169     tcic_setb(TCIC_AUX, data);
0170 }
0171 
0172 static u_short tcic_aux_getw(u_short reg)
0173 {
0174     u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
0175     tcic_setb(TCIC_MODE, mode);
0176     return tcic_getw(TCIC_AUX);
0177 }
0178 
0179 static void tcic_aux_setw(u_short reg, u_short data)
0180 {
0181     u_char mode = (tcic_getb(TCIC_MODE) & TCIC_MODE_PGMMASK) | reg;
0182     tcic_setb(TCIC_MODE, mode);
0183     tcic_setw(TCIC_AUX, data);
0184 }
0185 
0186 /*====================================================================*/
0187 
0188 /* Time conversion functions */
0189 
0190 static int to_cycles(int ns)
0191 {
0192     if (ns < 14)
0193     return 0;
0194     else
0195     return 2*(ns-14)/cycle_time;
0196 }
0197 
0198 /*====================================================================*/
0199 
0200 static volatile u_int irq_hits;
0201 
0202 static irqreturn_t __init tcic_irq_count(int irq, void *dev)
0203 {
0204     irq_hits++;
0205     return IRQ_HANDLED;
0206 }
0207 
0208 static u_int __init try_irq(int irq)
0209 {
0210     u_short cfg;
0211 
0212     irq_hits = 0;
0213     if (request_irq(irq, tcic_irq_count, 0, "irq scan", tcic_irq_count) != 0)
0214     return -1;
0215     mdelay(10);
0216     if (irq_hits) {
0217     free_irq(irq, tcic_irq_count);
0218     return -1;
0219     }
0220 
0221     /* Generate one interrupt */
0222     cfg = TCIC_SYSCFG_AUTOBUSY | 0x0a00;
0223     tcic_aux_setw(TCIC_AUX_SYSCFG, cfg | TCIC_IRQ(irq));
0224     tcic_setb(TCIC_IENA, TCIC_IENA_ERR | TCIC_IENA_CFG_HIGH);
0225     tcic_setb(TCIC_ICSR, TCIC_ICSR_ERR | TCIC_ICSR_JAM);
0226 
0227     udelay(1000);
0228     free_irq(irq, tcic_irq_count);
0229 
0230     /* Turn off interrupts */
0231     tcic_setb(TCIC_IENA, TCIC_IENA_CFG_OFF);
0232     while (tcic_getb(TCIC_ICSR))
0233     tcic_setb(TCIC_ICSR, TCIC_ICSR_JAM);
0234     tcic_aux_setw(TCIC_AUX_SYSCFG, cfg);
0235     
0236     return (irq_hits != 1);
0237 }
0238 
0239 static u_int __init irq_scan(u_int mask0)
0240 {
0241     u_int mask1;
0242     int i;
0243 
0244 #ifdef __alpha__
0245 #define PIC 0x4d0
0246     /* Don't probe level-triggered interrupts -- reserved for PCI */
0247     int level_mask = inb_p(PIC) | (inb_p(PIC+1) << 8);
0248     if (level_mask)
0249     mask0 &= ~level_mask;
0250 #endif
0251 
0252     mask1 = 0;
0253     if (do_scan) {
0254     for (i = 0; i < 16; i++)
0255         if ((mask0 & (1 << i)) && (try_irq(i) == 0))
0256         mask1 |= (1 << i);
0257     for (i = 0; i < 16; i++)
0258         if ((mask1 & (1 << i)) && (try_irq(i) != 0)) {
0259         mask1 ^= (1 << i);
0260         }
0261     }
0262     
0263     if (mask1) {
0264     printk("scanned");
0265     } else {
0266     /* Fallback: just find interrupts that aren't in use */
0267     for (i = 0; i < 16; i++)
0268         if ((mask0 & (1 << i)) &&
0269         (request_irq(i, tcic_irq_count, 0, "x", tcic_irq_count) == 0)) {
0270         mask1 |= (1 << i);
0271         free_irq(i, tcic_irq_count);
0272         }
0273     printk("default");
0274     }
0275     
0276     printk(") = ");
0277     for (i = 0; i < 16; i++)
0278     if (mask1 & (1<<i))
0279         printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
0280     printk(" ");
0281     
0282     return mask1;
0283 }
0284 
0285 /*======================================================================
0286 
0287     See if a card is present, powered up, in IO mode, and already
0288     bound to a (non-PCMCIA) Linux driver.
0289 
0290     We make an exception for cards that look like serial devices.
0291     
0292 ======================================================================*/
0293 
0294 static int __init is_active(int s)
0295 {
0296     u_short scf1, ioctl, base, num;
0297     u_char pwr, sstat;
0298     u_int addr;
0299     
0300     tcic_setl(TCIC_ADDR, (s << TCIC_ADDR_SS_SHFT)
0301           | TCIC_ADDR_INDREG | TCIC_SCF1(s));
0302     scf1 = tcic_getw(TCIC_DATA);
0303     pwr = tcic_getb(TCIC_PWR);
0304     sstat = tcic_getb(TCIC_SSTAT);
0305     addr = TCIC_IWIN(s, 0);
0306     tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
0307     base = tcic_getw(TCIC_DATA);
0308     tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
0309     ioctl = tcic_getw(TCIC_DATA);
0310 
0311     if (ioctl & TCIC_ICTL_TINY)
0312     num = 1;
0313     else {
0314     num = (base ^ (base-1));
0315     base = base & (base-1);
0316     }
0317 
0318     if ((sstat & TCIC_SSTAT_CD) && (pwr & TCIC_PWR_VCC(s)) &&
0319     (scf1 & TCIC_SCF1_IOSTS) && (ioctl & TCIC_ICTL_ENA) &&
0320     ((base & 0xfeef) != 0x02e8)) {
0321     struct resource *res = request_region(base, num, "tcic-2");
0322     if (!res) /* region is busy */
0323         return 1;
0324     release_region(base, num);
0325     }
0326 
0327     return 0;
0328 }
0329 
0330 /*======================================================================
0331 
0332     This returns the revision code for the specified socket.
0333     
0334 ======================================================================*/
0335 
0336 static int __init get_tcic_id(void)
0337 {
0338     u_short id;
0339     
0340     tcic_aux_setw(TCIC_AUX_TEST, TCIC_TEST_DIAG);
0341     id = tcic_aux_getw(TCIC_AUX_ILOCK);
0342     id = (id & TCIC_ILOCKTEST_ID_MASK) >> TCIC_ILOCKTEST_ID_SH;
0343     tcic_aux_setw(TCIC_AUX_TEST, 0);
0344     return id;
0345 }
0346 
0347 /*====================================================================*/
0348 
0349 static struct platform_driver tcic_driver = {
0350     .driver = {
0351         .name = "tcic-pcmcia",
0352     },
0353 };
0354 
0355 static struct platform_device tcic_device = {
0356     .name = "tcic-pcmcia",
0357     .id = 0,
0358 };
0359 
0360 
0361 static int __init init_tcic(void)
0362 {
0363     int i, sock, ret = 0;
0364     u_int mask, scan;
0365 
0366     if (platform_driver_register(&tcic_driver))
0367     return -1;
0368     
0369     printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: ");
0370     sock = 0;
0371 
0372     if (!request_region(tcic_base, 16, "tcic-2")) {
0373     printk("could not allocate ports,\n ");
0374     platform_driver_unregister(&tcic_driver);
0375     return -ENODEV;
0376     }
0377     else {
0378     tcic_setw(TCIC_ADDR, 0);
0379     if (tcic_getw(TCIC_ADDR) == 0) {
0380         tcic_setw(TCIC_ADDR, 0xc3a5);
0381         if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
0382     }
0383     if (sock == 0) {
0384         /* See if resetting the controller does any good */
0385         tcic_setb(TCIC_SCTRL, TCIC_SCTRL_RESET);
0386         tcic_setb(TCIC_SCTRL, 0);
0387         tcic_setw(TCIC_ADDR, 0);
0388         if (tcic_getw(TCIC_ADDR) == 0) {
0389         tcic_setw(TCIC_ADDR, 0xc3a5);
0390         if (tcic_getw(TCIC_ADDR) == 0xc3a5) sock = 2;
0391         }
0392     }
0393     }
0394     if (sock == 0) {
0395     printk("not found.\n");
0396     release_region(tcic_base, 16);
0397     platform_driver_unregister(&tcic_driver);
0398     return -ENODEV;
0399     }
0400 
0401     sockets = 0;
0402     for (i = 0; i < sock; i++) {
0403     if ((i == ignore) || is_active(i)) continue;
0404     socket_table[sockets].psock = i;
0405     socket_table[sockets].id = get_tcic_id();
0406 
0407     socket_table[sockets].socket.owner = THIS_MODULE;
0408     /* only 16-bit cards, memory windows must be size-aligned */
0409     /* No PCI or CardBus support */
0410     socket_table[sockets].socket.features = SS_CAP_PCCARD | SS_CAP_MEM_ALIGN;
0411     /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
0412     socket_table[sockets].socket.irq_mask = 0x4cf8;
0413     /* 4K minimum window size */
0414     socket_table[sockets].socket.map_size = 0x1000;     
0415     sockets++;
0416     }
0417 
0418     switch (socket_table[0].id) {
0419     case TCIC_ID_DB86082:
0420     printk("DB86082"); break;
0421     case TCIC_ID_DB86082A:
0422     printk("DB86082A"); break;
0423     case TCIC_ID_DB86084:
0424     printk("DB86084"); break;
0425     case TCIC_ID_DB86084A:
0426     printk("DB86084A"); break;
0427     case TCIC_ID_DB86072:
0428     printk("DB86072"); break;
0429     case TCIC_ID_DB86184:
0430     printk("DB86184"); break;
0431     case TCIC_ID_DB86082B:
0432     printk("DB86082B"); break;
0433     default:
0434     printk("Unknown ID 0x%02x", socket_table[0].id);
0435     }
0436     
0437     /* Set up polling */
0438     timer_setup(&poll_timer, &tcic_timer, 0);
0439 
0440     /* Build interrupt mask */
0441     printk(KERN_CONT ", %d sockets\n", sockets);
0442     printk(KERN_INFO "  irq list (");
0443     if (irq_list_count == 0)
0444     mask = irq_mask;
0445     else
0446     for (i = mask = 0; i < irq_list_count; i++)
0447         mask |= (1<<irq_list[i]);
0448 
0449     /* irq 14, 11, 10, 7, 6, 5, 4, 3 */
0450     mask &= 0x4cf8;
0451     /* Scan interrupts */
0452     mask = irq_scan(mask);
0453     for (i=0;i<sockets;i++)
0454         socket_table[i].socket.irq_mask = mask;
0455     
0456     /* Check for only two interrupts available */
0457     scan = (mask & (mask-1));
0458     if (((scan & (scan-1)) == 0) && (poll_interval == 0))
0459     poll_interval = HZ;
0460     
0461     if (poll_interval == 0) {
0462     /* Avoid irq 12 unless it is explicitly requested */
0463     u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
0464     for (i = 15; i > 0; i--)
0465         if ((cs_mask & (1 << i)) &&
0466         (request_irq(i, tcic_interrupt, 0, "tcic",
0467                  tcic_interrupt) == 0))
0468         break;
0469     cs_irq = i;
0470     if (cs_irq == 0) poll_interval = HZ;
0471     }
0472     
0473     if (socket_table[0].socket.irq_mask & (1 << 11))
0474     printk("sktirq is irq 11, ");
0475     if (cs_irq != 0)
0476     printk("status change on irq %d\n", cs_irq);
0477     else
0478     printk("polled status, interval = %d ms\n",
0479            poll_interval * 1000 / HZ);
0480     
0481     for (i = 0; i < sockets; i++) {
0482     tcic_setw(TCIC_ADDR+2, socket_table[i].psock << TCIC_SS_SHFT);
0483     socket_table[i].last_sstat = tcic_getb(TCIC_SSTAT);
0484     }
0485     
0486     /* jump start interrupt handler, if needed */
0487     tcic_interrupt(0, NULL);
0488 
0489     platform_device_register(&tcic_device);
0490 
0491     for (i = 0; i < sockets; i++) {
0492         socket_table[i].socket.ops = &tcic_operations;
0493         socket_table[i].socket.resource_ops = &pccard_nonstatic_ops;
0494         socket_table[i].socket.dev.parent = &tcic_device.dev;
0495         ret = pcmcia_register_socket(&socket_table[i].socket);
0496         if (ret && i)
0497             pcmcia_unregister_socket(&socket_table[0].socket);
0498     }
0499     
0500     return ret;
0501 
0502     return 0;
0503     
0504 } /* init_tcic */
0505 
0506 /*====================================================================*/
0507 
0508 static void __exit exit_tcic(void)
0509 {
0510     int i;
0511 
0512     del_timer_sync(&poll_timer);
0513     if (cs_irq != 0) {
0514     tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00);
0515     free_irq(cs_irq, tcic_interrupt);
0516     }
0517     release_region(tcic_base, 16);
0518 
0519     for (i = 0; i < sockets; i++) {
0520         pcmcia_unregister_socket(&socket_table[i].socket);      
0521     }
0522 
0523     platform_device_unregister(&tcic_device);
0524     platform_driver_unregister(&tcic_driver);
0525 } /* exit_tcic */
0526 
0527 /*====================================================================*/
0528 
0529 static irqreturn_t tcic_interrupt(int irq, void *dev)
0530 {
0531     int i, quick = 0;
0532     u_char latch, sstat;
0533     u_short psock;
0534     u_int events;
0535     static volatile int active = 0;
0536 
0537     if (active) {
0538     printk(KERN_NOTICE "tcic: reentered interrupt handler!\n");
0539     return IRQ_NONE;
0540     } else
0541     active = 1;
0542 
0543     pr_debug("tcic_interrupt()\n");
0544     
0545     for (i = 0; i < sockets; i++) {
0546     psock = socket_table[i].psock;
0547     tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
0548           | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
0549     sstat = tcic_getb(TCIC_SSTAT);
0550     latch = sstat ^ socket_table[psock].last_sstat;
0551     socket_table[i].last_sstat = sstat;
0552     if (tcic_getb(TCIC_ICSR) & TCIC_ICSR_CDCHG) {
0553         tcic_setb(TCIC_ICSR, TCIC_ICSR_CLEAR);
0554         quick = 1;
0555     }
0556     if (latch == 0)
0557         continue;
0558     events = (latch & TCIC_SSTAT_CD) ? SS_DETECT : 0;
0559     events |= (latch & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
0560     if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
0561         events |= (latch & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
0562     } else {
0563         events |= (latch & TCIC_SSTAT_RDY) ? SS_READY : 0;
0564         events |= (latch & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
0565         events |= (latch & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
0566     }
0567     if (events) {
0568         pcmcia_parse_events(&socket_table[i].socket, events);
0569     }
0570     }
0571 
0572     /* Schedule next poll, if needed */
0573     if (((cs_irq == 0) || quick) && (!tcic_timer_pending)) {
0574     poll_timer.expires = jiffies + (quick ? poll_quick : poll_interval);
0575     add_timer(&poll_timer);
0576     tcic_timer_pending = 1;
0577     }
0578     active = 0;
0579     
0580     pr_debug("interrupt done\n");
0581     return IRQ_HANDLED;
0582 } /* tcic_interrupt */
0583 
0584 static void tcic_timer(struct timer_list *unused)
0585 {
0586     pr_debug("tcic_timer()\n");
0587     tcic_timer_pending = 0;
0588     tcic_interrupt(0, NULL);
0589 } /* tcic_timer */
0590 
0591 /*====================================================================*/
0592 
0593 static int tcic_get_status(struct pcmcia_socket *sock, u_int *value)
0594 {
0595     u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
0596     u_char reg;
0597 
0598     tcic_setl(TCIC_ADDR, (psock << TCIC_ADDR_SS_SHFT)
0599           | TCIC_ADDR_INDREG | TCIC_SCF1(psock));
0600     reg = tcic_getb(TCIC_SSTAT);
0601     *value  = (reg & TCIC_SSTAT_CD) ? SS_DETECT : 0;
0602     *value |= (reg & TCIC_SSTAT_WP) ? SS_WRPROT : 0;
0603     if (tcic_getw(TCIC_DATA) & TCIC_SCF1_IOSTS) {
0604     *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_STSCHG : 0;
0605     } else {
0606     *value |= (reg & TCIC_SSTAT_RDY) ? SS_READY : 0;
0607     *value |= (reg & TCIC_SSTAT_LBAT1) ? SS_BATDEAD : 0;
0608     *value |= (reg & TCIC_SSTAT_LBAT2) ? SS_BATWARN : 0;
0609     }
0610     reg = tcic_getb(TCIC_PWR);
0611     if (reg & (TCIC_PWR_VCC(psock)|TCIC_PWR_VPP(psock)))
0612     *value |= SS_POWERON;
0613     dev_dbg(&sock->dev, "GetStatus(%d) = %#2.2x\n", psock, *value);
0614     return 0;
0615 } /* tcic_get_status */
0616 
0617 /*====================================================================*/
0618 
0619 static int tcic_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
0620 {
0621     u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
0622     u_char reg;
0623     u_short scf1, scf2;
0624 
0625     dev_dbg(&sock->dev, "SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
0626       "io_irq %d, csc_mask %#2.2x)\n", psock, state->flags,
0627       state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
0628     tcic_setw(TCIC_ADDR+2, (psock << TCIC_SS_SHFT) | TCIC_ADR2_INDREG);
0629 
0630     reg = tcic_getb(TCIC_PWR);
0631     reg &= ~(TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock));
0632 
0633     if (state->Vcc == 50) {
0634     switch (state->Vpp) {
0635     case 0:   reg |= TCIC_PWR_VCC(psock) | TCIC_PWR_VPP(psock); break;
0636     case 50:  reg |= TCIC_PWR_VCC(psock); break;
0637     case 120: reg |= TCIC_PWR_VPP(psock); break;
0638     default:  return -EINVAL;
0639     }
0640     } else if (state->Vcc != 0)
0641     return -EINVAL;
0642 
0643     if (reg != tcic_getb(TCIC_PWR))
0644     tcic_setb(TCIC_PWR, reg);
0645 
0646     reg = TCIC_ILOCK_HOLD_CCLK | TCIC_ILOCK_CWAIT;
0647     if (state->flags & SS_OUTPUT_ENA) {
0648     tcic_setb(TCIC_SCTRL, TCIC_SCTRL_ENA);
0649     reg |= TCIC_ILOCK_CRESENA;
0650     } else
0651     tcic_setb(TCIC_SCTRL, 0);
0652     if (state->flags & SS_RESET)
0653     reg |= TCIC_ILOCK_CRESET;
0654     tcic_aux_setb(TCIC_AUX_ILOCK, reg);
0655     
0656     tcic_setw(TCIC_ADDR, TCIC_SCF1(psock));
0657     scf1 = TCIC_SCF1_FINPACK;
0658     scf1 |= TCIC_IRQ(state->io_irq);
0659     if (state->flags & SS_IOCARD) {
0660     scf1 |= TCIC_SCF1_IOSTS;
0661     if (state->flags & SS_SPKR_ENA)
0662         scf1 |= TCIC_SCF1_SPKR;
0663     if (state->flags & SS_DMA_MODE)
0664         scf1 |= TCIC_SCF1_DREQ2 << TCIC_SCF1_DMA_SHIFT;
0665     }
0666     tcic_setw(TCIC_DATA, scf1);
0667 
0668     /* Some general setup stuff, and configure status interrupt */
0669     reg = TCIC_WAIT_ASYNC | TCIC_WAIT_SENSE | to_cycles(250);
0670     tcic_aux_setb(TCIC_AUX_WCTL, reg);
0671     tcic_aux_setw(TCIC_AUX_SYSCFG, TCIC_SYSCFG_AUTOBUSY|0x0a00|
0672           TCIC_IRQ(cs_irq));
0673     
0674     /* Card status change interrupt mask */
0675     tcic_setw(TCIC_ADDR, TCIC_SCF2(psock));
0676     scf2 = TCIC_SCF2_MALL;
0677     if (state->csc_mask & SS_DETECT) scf2 &= ~TCIC_SCF2_MCD;
0678     if (state->flags & SS_IOCARD) {
0679     if (state->csc_mask & SS_STSCHG) reg &= ~TCIC_SCF2_MLBAT1;
0680     } else {
0681     if (state->csc_mask & SS_BATDEAD) reg &= ~TCIC_SCF2_MLBAT1;
0682     if (state->csc_mask & SS_BATWARN) reg &= ~TCIC_SCF2_MLBAT2;
0683     if (state->csc_mask & SS_READY) reg &= ~TCIC_SCF2_MRDY;
0684     }
0685     tcic_setw(TCIC_DATA, scf2);
0686     /* For the ISA bus, the irq should be active-high totem-pole */
0687     tcic_setb(TCIC_IENA, TCIC_IENA_CDCHG | TCIC_IENA_CFG_HIGH);
0688 
0689     return 0;
0690 } /* tcic_set_socket */
0691   
0692 /*====================================================================*/
0693 
0694 static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
0695 {
0696     u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
0697     u_int addr;
0698     u_short base, len, ioctl;
0699     
0700     dev_dbg(&sock->dev, "SetIOMap(%d, %d, %#2.2x, %d ns, "
0701       "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,
0702       (unsigned long long)io->start, (unsigned long long)io->stop);
0703     if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
0704     (io->stop < io->start)) return -EINVAL;
0705     tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
0706     addr = TCIC_IWIN(psock, io->map);
0707 
0708     base = io->start; len = io->stop - io->start;
0709     /* Check to see that len+1 is power of two, etc */
0710     if ((len & (len+1)) || (base & len)) return -EINVAL;
0711     base |= (len+1)>>1;
0712     tcic_setw(TCIC_ADDR, addr + TCIC_IBASE_X);
0713     tcic_setw(TCIC_DATA, base);
0714     
0715     ioctl  = (psock << TCIC_ICTL_SS_SHFT);
0716     ioctl |= (len == 0) ? TCIC_ICTL_TINY : 0;
0717     ioctl |= (io->flags & MAP_ACTIVE) ? TCIC_ICTL_ENA : 0;
0718     ioctl |= to_cycles(io->speed) & TCIC_ICTL_WSCNT_MASK;
0719     if (!(io->flags & MAP_AUTOSZ)) {
0720     ioctl |= TCIC_ICTL_QUIET;
0721     ioctl |= (io->flags & MAP_16BIT) ? TCIC_ICTL_BW_16 : TCIC_ICTL_BW_8;
0722     }
0723     tcic_setw(TCIC_ADDR, addr + TCIC_ICTL_X);
0724     tcic_setw(TCIC_DATA, ioctl);
0725     
0726     return 0;
0727 } /* tcic_set_io_map */
0728 
0729 /*====================================================================*/
0730 
0731 static int tcic_set_mem_map(struct pcmcia_socket *sock, struct pccard_mem_map *mem)
0732 {
0733     u_short psock = container_of(sock, struct tcic_socket, socket)->psock;
0734     u_short addr, ctl;
0735     u_long base, len, mmap;
0736 
0737     dev_dbg(&sock->dev, "SetMemMap(%d, %d, %#2.2x, %d ns, "
0738       "%#llx-%#llx, %#x)\n", psock, mem->map, mem->flags,
0739       mem->speed, (unsigned long long)mem->res->start,
0740       (unsigned long long)mem->res->end, mem->card_start);
0741     if ((mem->map > 3) || (mem->card_start > 0x3ffffff) ||
0742     (mem->res->start > 0xffffff) || (mem->res->end > 0xffffff) ||
0743     (mem->res->start > mem->res->end) || (mem->speed > 1000))
0744     return -EINVAL;
0745     tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
0746     addr = TCIC_MWIN(psock, mem->map);
0747 
0748     base = mem->res->start; len = mem->res->end - mem->res->start;
0749     if ((len & (len+1)) || (base & len)) return -EINVAL;
0750     if (len == 0x0fff)
0751     base = (base >> TCIC_MBASE_HA_SHFT) | TCIC_MBASE_4K_BIT;
0752     else
0753     base = (base | (len+1)>>1) >> TCIC_MBASE_HA_SHFT;
0754     tcic_setw(TCIC_ADDR, addr + TCIC_MBASE_X);
0755     tcic_setw(TCIC_DATA, base);
0756     
0757     mmap = mem->card_start - mem->res->start;
0758     mmap = (mmap >> TCIC_MMAP_CA_SHFT) & TCIC_MMAP_CA_MASK;
0759     if (mem->flags & MAP_ATTRIB) mmap |= TCIC_MMAP_REG;
0760     tcic_setw(TCIC_ADDR, addr + TCIC_MMAP_X);
0761     tcic_setw(TCIC_DATA, mmap);
0762 
0763     ctl  = TCIC_MCTL_QUIET | (psock << TCIC_MCTL_SS_SHFT);
0764     ctl |= to_cycles(mem->speed) & TCIC_MCTL_WSCNT_MASK;
0765     ctl |= (mem->flags & MAP_16BIT) ? 0 : TCIC_MCTL_B8;
0766     ctl |= (mem->flags & MAP_WRPROT) ? TCIC_MCTL_WP : 0;
0767     ctl |= (mem->flags & MAP_ACTIVE) ? TCIC_MCTL_ENA : 0;
0768     tcic_setw(TCIC_ADDR, addr + TCIC_MCTL_X);
0769     tcic_setw(TCIC_DATA, ctl);
0770     
0771     return 0;
0772 } /* tcic_set_mem_map */
0773 
0774 /*====================================================================*/
0775 
0776 static int tcic_init(struct pcmcia_socket *s)
0777 {
0778     int i;
0779     struct resource res = { .start = 0, .end = 0x1000 };
0780     pccard_io_map io = { 0, 0, 0, 0, 1 };
0781     pccard_mem_map mem = { .res = &res, };
0782 
0783     for (i = 0; i < 2; i++) {
0784         io.map = i;
0785         tcic_set_io_map(s, &io);
0786     }
0787     for (i = 0; i < 5; i++) {
0788         mem.map = i;
0789         tcic_set_mem_map(s, &mem);
0790     }
0791     return 0;
0792 }
0793 
0794 static struct pccard_operations tcic_operations = {
0795     .init          = tcic_init,
0796     .get_status    = tcic_get_status,
0797     .set_socket    = tcic_set_socket,
0798     .set_io_map    = tcic_set_io_map,
0799     .set_mem_map       = tcic_set_mem_map,
0800 };
0801 
0802 /*====================================================================*/
0803 
0804 module_init(init_tcic);
0805 module_exit(exit_tcic);