^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);