^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Driver for the Cirrus PD6729 PCI-PCMCIA bridge.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Based on the i82092.c driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This software may be used and distributed according to the terms of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * the GNU General Public License, incorporated herein by reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <pcmcia/ss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "pd6729.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "i82365.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "cirrus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) MODULE_DESCRIPTION("Driver for the Cirrus PD6729 PCI-PCMCIA bridge");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) MODULE_AUTHOR("Jun Komuro <komurojun-mbn@nifty.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define MAX_SOCKETS 2
^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) * simple helper functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * External clock time, in nanoseconds. 120 ns = 8.33 MHz
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define to_cycles(ns) ((ns)/120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #ifndef NO_IRQ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define NO_IRQ ((unsigned int)(0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * PARAMETERS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * irq_mode=n
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * Specifies the interrupt delivery mode. The default (1) is to use PCI
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * interrupts; a value of 0 selects ISA interrupts. This must be set for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * correct operation of PCI card readers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int irq_mode = 1; /* 0 = ISA interrupt, 1 = PCI interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) module_param(irq_mode, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MODULE_PARM_DESC(irq_mode,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) "interrupt delivery mode. 0 = ISA, 1 = PCI. default is 1");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) static DEFINE_SPINLOCK(port_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) /* basic value read/write functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) static unsigned char indirect_read(struct pd6729_socket *socket,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) spin_lock_irqsave(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) reg += socket->number * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) port = socket->io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) val = inb(port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) spin_unlock_irqrestore(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static unsigned short indirect_read16(struct pd6729_socket *socket,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned short tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) spin_lock_irqsave(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) reg = reg + socket->number * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) port = socket->io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) tmp = inb(port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) reg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) tmp = tmp | (inb(port + 1) << 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) spin_unlock_irqrestore(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static void indirect_write(struct pd6729_socket *socket, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) unsigned char value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) spin_lock_irqsave(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) reg = reg + socket->number * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) port = socket->io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) outb(value, port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) spin_unlock_irqrestore(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static void indirect_setbit(struct pd6729_socket *socket, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned char mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) spin_lock_irqsave(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) reg = reg + socket->number * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) port = socket->io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) val = inb(port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) val |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) outb(val, port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) spin_unlock_irqrestore(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static void indirect_resetbit(struct pd6729_socket *socket, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) unsigned char mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) spin_lock_irqsave(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) reg = reg + socket->number * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) port = socket->io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) val = inb(port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) val &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) outb(val, port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) spin_unlock_irqrestore(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) static void indirect_write16(struct pd6729_socket *socket, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) unsigned short value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) unsigned long port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) unsigned char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) spin_lock_irqsave(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) reg = reg + socket->number * 0x40;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) port = socket->io_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) val = value & 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) outb(val, port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) reg++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) outb(reg, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) val = value >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) outb(val, port + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) spin_unlock_irqrestore(&port_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /* Interrupt handler functionality */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) static irqreturn_t pd6729_interrupt(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) struct pd6729_socket *socket = (struct pd6729_socket *)dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) int loopcount = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) unsigned int events, active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) loopcount++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (loopcount > 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) printk(KERN_ERR "pd6729: infinite eventloop "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) "in interrupt\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) for (i = 0; i < MAX_SOCKETS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) unsigned int csc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /* card status change register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) csc = indirect_read(&socket[i], I365_CSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (csc == 0) /* no events on this socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) events = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (csc & I365_CSC_DETECT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) events |= SS_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dev_vdbg(&socket[i].socket.dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "Card detected in socket %i!\n", i);
^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) if (indirect_read(&socket[i], I365_INTCTL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) & I365_PC_IOCARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /* For IO/CARDS, bit 0 means "read the card" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) events |= (csc & I365_CSC_STSCHG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) ? SS_STSCHG : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) /* Check for battery/ready events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) events |= (csc & I365_CSC_BVD1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) ? SS_BATDEAD : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) events |= (csc & I365_CSC_BVD2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) ? SS_BATWARN : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) events |= (csc & I365_CSC_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ? SS_READY : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) pcmcia_parse_events(&socket[i].socket, events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) active |= events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (active == 0) /* no more events to handle */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return IRQ_RETVAL(handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* socket functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static void pd6729_interrupt_wrapper(struct timer_list *t)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct pd6729_socket *socket = from_timer(socket, t, poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) pd6729_interrupt(0, (void *)socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) mod_timer(&socket->poll_timer, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) static int pd6729_get_status(struct pcmcia_socket *sock, u_int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) struct pd6729_socket *socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) = container_of(sock, struct pd6729_socket, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) unsigned int data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct pd6729_socket *t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* Interface Status Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) status = indirect_read(socket, I365_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) *value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) if ((status & I365_CS_DETECT) == I365_CS_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *value |= SS_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) * IO cards have a different meaning of bits 0,1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * Also notice the inverse-logic on the bits
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) if (indirect_read(socket, I365_INTCTL) & I365_PC_IOCARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /* IO card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (!(status & I365_CS_STSCHG))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) *value |= SS_STSCHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* non I/O card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (!(status & I365_CS_BVD1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) *value |= SS_BATDEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (!(status & I365_CS_BVD2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) *value |= SS_BATWARN;
^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) if (status & I365_CS_WRPROT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) *value |= SS_WRPROT; /* card is write protected */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (status & I365_CS_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) *value |= SS_READY; /* card is not busy */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) if (status & I365_CS_POWERON)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) *value |= SS_POWERON; /* power is applied to the card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) t = (socket->number) ? socket : socket + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) indirect_write(t, PD67_EXT_INDEX, PD67_EXTERN_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) data = indirect_read16(t, PD67_EXT_DATA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) *value |= (data & PD67_EXD_VS1(socket->number)) ? 0 : SS_3VCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return 0;
^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 pd6729_set_socket(struct pcmcia_socket *sock, socket_state_t *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct pd6729_socket *socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) = container_of(sock, struct pd6729_socket, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) unsigned char reg, data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) /* First, set the global controller options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) indirect_write(socket, I365_GBLCTL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) indirect_write(socket, I365_GENCTL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /* Values for the IGENC register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) socket->card_irq = state->io_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) reg = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* The reset bit has "inverse" logic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) if (!(state->flags & SS_RESET))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) reg |= I365_PC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (state->flags & SS_IOCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) reg |= I365_PC_IOCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) /* IGENC, Interrupt and General Control Register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) indirect_write(socket, I365_INTCTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) /* Power registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) reg = I365_PWR_NORESET; /* default: disable resetdrv on resume */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (state->flags & SS_PWR_AUTO) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) dev_dbg(&sock->dev, "Auto power\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) reg |= I365_PWR_AUTO; /* automatic power mngmnt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (state->flags & SS_OUTPUT_ENA) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) dev_dbg(&sock->dev, "Power Enabled\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) reg |= I365_PWR_OUT; /* enable power */
^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) switch (state->Vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) case 33:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) dev_dbg(&sock->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) "setting voltage to Vcc to 3.3V on socket %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) socket->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) reg |= I365_VCC_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) indirect_setbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) case 50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_dbg(&sock->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) "setting voltage to Vcc to 5V on socket %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) socket->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) reg |= I365_VCC_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) indirect_resetbit(socket, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dev_dbg(&sock->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) "pd6729_set_socket called with invalid VCC power "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) "value: %i\n", state->Vcc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return -EINVAL;
^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) switch (state->Vpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) dev_dbg(&sock->dev, "not setting Vpp on socket %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) socket->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) case 33:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) case 50:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) dev_dbg(&sock->dev, "setting Vpp to Vcc for socket %i\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) socket->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) reg |= I365_VPP1_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) case 120:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) dev_dbg(&sock->dev, "setting Vpp to 12.0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) reg |= I365_VPP1_12V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) dev_dbg(&sock->dev, "pd6729: pd6729_set_socket called with "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) "invalid VPP power value: %i\n", state->Vpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) /* only write if changed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) if (reg != indirect_read(socket, I365_POWER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) indirect_write(socket, I365_POWER, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (irq_mode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) /* all interrupts are to be done as PCI interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) data = PD67_EC1_INV_MGMT_IRQ | PD67_EC1_INV_CARD_IRQ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) data = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) indirect_write(socket, PD67_EXT_INDEX, PD67_EXT_CTL_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) indirect_write(socket, PD67_EXT_DATA, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) /* Enable specific interrupt events */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) reg = 0x00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) if (state->csc_mask & SS_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) reg |= I365_CSC_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) if (state->flags & SS_IOCARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (state->csc_mask & SS_STSCHG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) reg |= I365_CSC_STSCHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (state->csc_mask & SS_BATDEAD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) reg |= I365_CSC_BVD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (state->csc_mask & SS_BATWARN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) reg |= I365_CSC_BVD2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (state->csc_mask & SS_READY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) reg |= I365_CSC_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) if (irq_mode == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) reg |= 0x30; /* management IRQ: PCI INTA# = "irq 3" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) indirect_write(socket, I365_CSCINT, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) reg = indirect_read(socket, I365_INTCTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (irq_mode == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) reg |= 0x03; /* card IRQ: PCI INTA# = "irq 3" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) reg |= socket->card_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) indirect_write(socket, I365_INTCTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* now clear the (probably bogus) pending stuff by doing a dummy read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) (void)indirect_read(socket, I365_CSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) static int pd6729_set_io_map(struct pcmcia_socket *sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) struct pccard_io_map *io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) struct pd6729_socket *socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) = container_of(sock, struct pd6729_socket, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) unsigned char map, ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) map = io->map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /* Check error conditions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) if (map > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) dev_dbg(&sock->dev, "pd6729_set_io_map with invalid map\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) return -EINVAL;
^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) /* Turn off the window before changing anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_IO(map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_IO(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) /* dev_dbg(&sock->dev, "set_io_map: Setting range to %x - %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) io->start, io->stop);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) /* write the new values */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) indirect_write16(socket, I365_IO(map)+I365_W_START, io->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) indirect_write16(socket, I365_IO(map)+I365_W_STOP, io->stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) ioctl = indirect_read(socket, I365_IOCTL) & ~I365_IOCTL_MASK(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) if (io->flags & MAP_0WS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) ioctl |= I365_IOCTL_0WS(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) if (io->flags & MAP_16BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) ioctl |= I365_IOCTL_16BIT(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) if (io->flags & MAP_AUTOSZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) ioctl |= I365_IOCTL_IOCS16(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) indirect_write(socket, I365_IOCTL, ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) /* Turn the window back on if needed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) if (io->flags & MAP_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) indirect_setbit(socket, I365_ADDRWIN, I365_ENA_IO(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) static int pd6729_set_mem_map(struct pcmcia_socket *sock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) struct pccard_mem_map *mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) struct pd6729_socket *socket
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) = container_of(sock, struct pd6729_socket, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) unsigned short base, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) unsigned char map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) map = mem->map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) if (map > 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) dev_warn(&sock->dev, "invalid map requested\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if ((mem->res->start > mem->res->end) || (mem->speed > 1000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) dev_warn(&sock->dev, "invalid invalid address / speed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) /* Turn off the window before changing anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (indirect_read(socket, I365_ADDRWIN) & I365_ENA_MEM(map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) indirect_resetbit(socket, I365_ADDRWIN, I365_ENA_MEM(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* write the start address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) base = I365_MEM(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) i = (mem->res->start >> 12) & 0x0fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (mem->flags & MAP_16BIT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) i |= I365_MEM_16BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) if (mem->flags & MAP_0WS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) i |= I365_MEM_0WS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) indirect_write16(socket, base + I365_W_START, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /* write the stop address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) i = (mem->res->end >> 12) & 0x0fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) switch (to_cycles(mem->speed)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) i |= I365_MEM_WS0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) i |= I365_MEM_WS1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) i |= I365_MEM_WS1 | I365_MEM_WS0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) indirect_write16(socket, base + I365_W_STOP, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) /* Take care of high byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) indirect_write(socket, PD67_EXT_INDEX, PD67_MEM_PAGE(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) indirect_write(socket, PD67_EXT_DATA, mem->res->start >> 24);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) /* card start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (mem->flags & MAP_WRPROT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) i |= I365_MEM_WRPROT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (mem->flags & MAP_ATTRIB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) /* dev_dbg(&sock->dev, "requesting attribute memory for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) "socket %i\n", socket->number);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) i |= I365_MEM_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) /* dev_dbg(&sock->dev, "requesting normal memory for "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) "socket %i\n", socket->number);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) indirect_write16(socket, base + I365_W_OFF, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) /* Enable the window if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (mem->flags & MAP_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) indirect_setbit(socket, I365_ADDRWIN, I365_ENA_MEM(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static int pd6729_init(struct pcmcia_socket *sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct resource res = { .end = 0x0fff };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) pccard_io_map io = { 0, 0, 0, 0, 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) pccard_mem_map mem = { .res = &res, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) pd6729_set_socket(sock, &dead_socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) io.map = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) pd6729_set_io_map(sock, &io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) mem.map = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) pd6729_set_mem_map(sock, &mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* the pccard structure and its functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) static struct pccard_operations pd6729_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) .init = pd6729_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) .get_status = pd6729_get_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) .set_socket = pd6729_set_socket,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) .set_io_map = pd6729_set_io_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) .set_mem_map = pd6729_set_mem_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static irqreturn_t pd6729_test(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) pr_devel("-> hit on irq %d\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) static int pd6729_check_irq(int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) ret = request_irq(irq, pd6729_test, IRQF_PROBE_SHARED, "x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) pd6729_test);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) free_irq(irq, pd6729_test);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return 0;
^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) static u_int pd6729_isa_scan(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) u_int mask0, mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (irq_mode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) printk(KERN_INFO "pd6729: PCI card interrupts, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) "PCI status changes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) mask0 = PD67_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) /* just find interrupts that aren't in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) if ((mask0 & (1 << i)) && (pd6729_check_irq(i) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) mask |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) printk(KERN_INFO "pd6729: ISA irqs = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if (mask & (1<<i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) printk("%s%d", ((mask & ((1<<i)-1)) ? "," : ""), i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) if (mask == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) printk("none!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) printk(" polling status changes.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static int pd6729_pci_probe(struct pci_dev *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) const struct pci_device_id *id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) int i, j, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) u_int mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) char configbyte;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) struct pd6729_socket *socket;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) socket = kcalloc(MAX_SOCKETS, sizeof(struct pd6729_socket),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) if (!socket) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) dev_warn(&dev->dev, "failed to kzalloc socket.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) ret = pci_enable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) dev_warn(&dev->dev, "failed to enable pci_device.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) goto err_out_free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) if (!pci_resource_start(dev, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) dev_warn(&dev->dev, "refusing to load the driver as the "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) "io_base is NULL.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) goto err_out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) dev_info(&dev->dev, "Cirrus PD6729 PCI to PCMCIA Bridge at 0x%llx "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) "on irq %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) (unsigned long long)pci_resource_start(dev, 0), dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) * Since we have no memory BARs some firmware may not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) * have had PCI_COMMAND_MEMORY enabled, yet the device needs it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) pci_read_config_byte(dev, PCI_COMMAND, &configbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (!(configbyte & PCI_COMMAND_MEMORY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) dev_dbg(&dev->dev, "pd6729: Enabling PCI_COMMAND_MEMORY.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) configbyte |= PCI_COMMAND_MEMORY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) pci_write_config_byte(dev, PCI_COMMAND, configbyte);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ret = pci_request_regions(dev, "pd6729");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) dev_warn(&dev->dev, "pci request region failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) goto err_out_disable;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) if (dev->irq == NO_IRQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) irq_mode = 0; /* fall back to ISA interrupt mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mask = pd6729_isa_scan();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (irq_mode == 0 && mask == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) dev_warn(&dev->dev, "no ISA interrupt is available.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) goto err_out_free_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) for (i = 0; i < MAX_SOCKETS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) socket[i].io_base = pci_resource_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) socket[i].socket.features |= SS_CAP_PAGE_REGS | SS_CAP_PCCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) socket[i].socket.map_size = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) socket[i].socket.irq_mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) socket[i].socket.pci_irq = dev->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) socket[i].socket.cb_dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) socket[i].socket.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) socket[i].number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) socket[i].socket.ops = &pd6729_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) socket[i].socket.resource_ops = &pccard_nonstatic_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) socket[i].socket.dev.parent = &dev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) socket[i].socket.driver_data = &socket[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) pci_set_drvdata(dev, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) if (irq_mode == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) /* Register the interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ret = request_irq(dev->irq, pd6729_interrupt, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) "pd6729", socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) dev_err(&dev->dev, "Failed to register irq %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) dev->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) goto err_out_free_res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) /* poll Card status change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) timer_setup(&socket->poll_timer, pd6729_interrupt_wrapper, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) mod_timer(&socket->poll_timer, jiffies + HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) for (i = 0; i < MAX_SOCKETS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ret = pcmcia_register_socket(&socket[i].socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) dev_warn(&dev->dev, "pcmcia_register_socket failed.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) for (j = 0; j < i ; j++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) pcmcia_unregister_socket(&socket[j].socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) goto err_out_free_res2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) err_out_free_res2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) if (irq_mode == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) free_irq(dev->irq, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) del_timer_sync(&socket->poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) err_out_free_res:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) err_out_disable:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) err_out_free_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) kfree(socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) static void pd6729_pci_remove(struct pci_dev *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) struct pd6729_socket *socket = pci_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) for (i = 0; i < MAX_SOCKETS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) /* Turn off all interrupt sources */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) indirect_write(&socket[i], I365_CSCINT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) indirect_write(&socket[i], I365_INTCTL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) pcmcia_unregister_socket(&socket[i].socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (irq_mode == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) free_irq(dev->irq, socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) del_timer_sync(&socket->poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) pci_release_regions(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) pci_disable_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) kfree(socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) static const struct pci_device_id pd6729_pci_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) { PCI_DEVICE(PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_6729) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) MODULE_DEVICE_TABLE(pci, pd6729_pci_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) static struct pci_driver pd6729_pci_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) .name = "pd6729",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) .id_table = pd6729_pci_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) .probe = pd6729_pci_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) .remove = pd6729_pci_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) module_pci_driver(pd6729_pci_driver);