patch-2.3.40 linux/drivers/pcmcia/yenta.c
Next file: linux/drivers/pnp/Makefile
Previous file: linux/drivers/pcmcia/ti113x.h
Back to the patch index
Back to the overall index
- Lines: 280
- Date:
Thu Jan 13 22:34:42 2000
- Orig file:
v2.3.39/linux/drivers/pcmcia/yenta.c
- Orig date:
Tue Jan 11 22:31:41 2000
diff -u --recursive --new-file v2.3.39/linux/drivers/pcmcia/yenta.c linux/drivers/pcmcia/yenta.c
@@ -15,7 +15,6 @@
#include "yenta.h"
#include "i82365.h"
-#include "ricoh.h"
/* Don't ask.. */
#define to_cycles(ns) ((ns)/120)
@@ -68,12 +67,6 @@
exca_writeb(socket, reg+1, val >> 8);
}
-static int yenta_inquire(pci_socket_t *socket, socket_cap_t *cap)
-{
- *cap = socket->cap;
- return 0;
-}
-
/*
* Ugh, mixed-mode cardbus and 16-bit pccard state: things depend
* on what kind of card is inserted..
@@ -190,20 +183,22 @@
u16 bridge;
yenta_set_power(socket, state);
- bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_CRST;
+ socket->io_irq = state->io_irq;
+ bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~(CB_BRIDGE_CRST | CB_BRIDGE_INTR);
if (cb_readl(socket, CB_SOCKET_STATE) & CB_CBCARD) {
bridge |= (state->flags & SS_RESET) ? CB_BRIDGE_CRST : 0;
- bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
/* ISA interrupt control? */
- if (bridge & CB_BRIDGE_INTR) {
+ if (!socket->cb_irq) {
u8 intr = exca_readb(socket, I365_INTCTL);
intr = (intr & ~0xf) | state->io_irq;
exca_writeb(socket, I365_INTCTL, intr);
+ bridge |= CB_BRIDGE_INTR;
}
} else {
u8 reg;
+ bridge |= CB_BRIDGE_INTR;
reg = exca_readb(socket, I365_INTCTL) & (I365_RING_ENA | I365_INTR_ENA);
reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
@@ -426,7 +421,7 @@
* more timely manner if the state change interrupt
* works..)
*/
-static int socket_thread(void * data)
+static int yenta_socket_thread(void * data)
{
pci_socket_t * socket = (pci_socket_t *) data;
DECLARE_WAITQUEUE(wait, current);
@@ -457,20 +452,10 @@
int i;
unsigned long val;
u16 bridge_ctrl;
+ u32 mask;
- /* Are we set up to route the IO irq to the PCI irq? */
+ /* Set up ISA irq routing to probe the ISA irqs.. */
bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL);
- if (socket->cb_irq) {
- if (bridge_ctrl & CB_BRIDGE_INTR) {
- bridge_ctrl &= ~CB_BRIDGE_INTR;
- config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
- }
- printk("CardBus: using PCI interrupt %d\n", socket->cb_irq);
- return 1 << socket->cb_irq;
- }
-
- /* Uhhuh. No PCI interrupt: try falling back on ISA interrupts */
- printk("CardBus: Hmm.. No PCI irq routing (irq%d).\n", socket->cb_irq);
if (!(bridge_ctrl & CB_BRIDGE_INTR)) {
bridge_ctrl |= CB_BRIDGE_INTR;
config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
@@ -492,7 +477,13 @@
cb_writel(socket, CB_SOCKET_EVENT, -1);
}
cb_writel(socket, CB_SOCKET_MASK, 0);
- return probe_irq_mask(val) & 0xffff;
+
+ mask = probe_irq_mask(val) & 0xffff;
+
+ bridge_ctrl &= ~CB_BRIDGE_INTR;
+ config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl);
+
+ return mask;
}
static void yenta_clear_maps(pci_socket_t *socket)
@@ -516,6 +507,7 @@
/* Called at resume and initialization events */
static int yenta_init(pci_socket_t *socket)
{
+ u16 bridge;
struct pci_dev *dev = socket->dev;
pci_set_power_state(socket->dev, 0);
@@ -536,6 +528,19 @@
config_writeb(socket, PCI_SECONDARY_BUS, dev->subordinate->number);
config_writeb(socket, PCI_SUBORDINATE_BUS, dev->subordinate->number);
+ /*
+ * Set up the bridging state:
+ * - enable write posting.
+ * - memory window 0 prefetchable, window 1 non-prefetchable
+ * - PCI interrupts enabled if a PCI interrupt exists..
+ */
+ bridge = config_readw(socket, CB_BRIDGE_CONTROL);
+ bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN);
+ bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN;
+ if (!socket->cb_irq)
+ bridge |= CB_BRIDGE_INTR;
+ config_writew(socket, CB_BRIDGE_CONTROL, bridge);
+
exca_writeb(socket, I365_GBLCTL, 0x00);
exca_writeb(socket, I365_GENCTL, 0x00);
@@ -543,29 +548,6 @@
return 0;
}
-/*
- * More of an example than anything else... The standard
- * yenta init code works well enough - but this is how
- * you'd do it if you wanted to have a special init sequence.
- */
-static int ricoh_init(pci_socket_t *socket)
-{
- u16 misc = config_readw(socket, RL5C4XX_MISC);
- u16 ctl = config_readw(socket, RL5C4XX_16BIT_CTL);
- u16 io = config_readw(socket, RL5C4XX_16BIT_IO_0);
- u16 mem = config_readw(socket, RL5C4XX_16BIT_MEM_0);
-
- ctl = RL5C4XX_16CTL_IO_TIMING | RL5C4XX_16CTL_MEM_TIMING;
-
- config_writew(socket, RL5C4XX_MISC, misc);
- config_writew(socket, RL5C4XX_16BIT_CTL, ctl);
- config_writew(socket, RL5C4XX_16BIT_IO_0, io);
- config_writew(socket, RL5C4XX_16BIT_MEM_0, mem);
-
- return yenta_init(socket);
-}
-
-
static int yenta_suspend(pci_socket_t *socket)
{
yenta_set_socket(socket, &dead_socket);
@@ -585,7 +567,7 @@
socket->cap.cb_dev = socket->dev;
socket->cap.bus = NULL;
- printk("Yenta IRQ list %04x\n", socket->cap.irq_mask);
+ printk("Yenta IRQ list %04x, PCI irq%d\n", socket->cap.irq_mask, socket->cb_irq);
}
static void yenta_allocate_res(pci_socket_t *socket, int nr, unsigned type)
@@ -618,11 +600,11 @@
}
align = size = 4*1024*1024;
- min = 0x10000000; max = ~0U;
+ min = PCIBIOS_MIN_MEM; max = ~0U;
if (type & IORESOURCE_IO) {
align = 1024;
size = 256;
- min = 0x1000;
+ min = PCIBIOS_MIN_IO;
max = 0xffff;
}
@@ -644,12 +626,50 @@
}
/*
+ * Close it down - release our resources and go home..
+ */
+static void yenta_close(pci_socket_t *sock)
+{
+ if (sock->cb_irq)
+ free_irq(sock->cb_irq, sock);
+ if (sock->base)
+ iounmap(sock->base);
+}
+
+#include "ti113x.h"
+#include "ricoh.h"
+
+/*
+ * Different cardbus controllers have slightly different
+ * initialization sequences etc details. List them here..
+ */
+#define PD(x,y) PCI_VENDOR_ID_##x, PCI_DEVICE_ID_##x##_##y
+static struct cardbus_override_struct {
+ unsigned short vendor;
+ unsigned short device;
+ struct pci_socket_ops *op;
+} cardbus_override[] = {
+ { PD(TI,1130), &ti113x_ops },
+ { PD(TI,1131), &ti113x_ops },
+ { PD(TI,1250), &ti1250_ops },
+
+ { PD(RICOH,RL5C465), &ricoh_ops },
+ { PD(RICOH,RL5C466), &ricoh_ops },
+ { PD(RICOH,RL5C475), &ricoh_ops },
+ { PD(RICOH,RL5C476), &ricoh_ops },
+ { PD(RICOH,RL5C478), &ricoh_ops }
+};
+
+#define NR_OVERRIDES (sizeof(cardbus_override)/sizeof(struct cardbus_override_struct))
+
+/*
* Initialize a cardbus controller. Make sure we have a usable
* interrupt, and that we can map the cardbus area. Fill in the
* socket information structure..
*/
static int yenta_open(pci_socket_t *socket)
{
+ int i;
struct pci_dev *dev = socket->dev;
/*
@@ -684,23 +704,25 @@
/* And figure out what the dang thing can do for the PCMCIA layer... */
yenta_get_socket_capabilities(socket);
- kernel_thread(socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+ /* Do we have special options for the device? */
+ for (i = 0; i < NR_OVERRIDES; i++) {
+ struct cardbus_override_struct *d = cardbus_override+i;
+ if (dev->vendor == d->vendor && dev->device == d->device) {
+ socket->op = d->op;
+ if (d->op->open) {
+ int retval = d->op->open(socket);
+ if (retval < 0)
+ return retval;
+ }
+ }
+ }
+
+ kernel_thread(yenta_socket_thread, socket, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
printk("Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE));
return 0;
}
/*
- * Close it down - release our resources and go home..
- */
-static void yenta_close(pci_socket_t *sock)
-{
- if (sock->cb_irq)
- free_irq(sock->cb_irq, sock);
- if (sock->base)
- iounmap(sock->base);
-}
-
-/*
* Standard plain cardbus - no frills, no extensions
*/
struct pci_socket_ops yenta_operations = {
@@ -708,7 +730,6 @@
yenta_close,
yenta_init,
yenta_suspend,
- yenta_inquire,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
@@ -728,7 +749,6 @@
yenta_close,
ricoh_init,
yenta_suspend,
- yenta_inquire,
yenta_get_status,
yenta_get_socket,
yenta_set_socket,
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)