Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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