[PATCH] yenta TI: turn off interrupts during card power-on #2

- make boot-up card recognition more reliable (ie.  redo interrogation
  always if there is no valid 'card inserted' state) (and yes, i saw it
  happening on an o2micro controller that both CB_CBARD and CB_16BITCARD
  bits were set at the same time)

- also redo interrogation before probing the ISA interrupts.  it's safer
  to do the probing with the socket in a clean state.

- make card insert detect more reliable.  yenta_get_status() now returns
  SS_PENDING as long as the card is not completley inserted and one of the
  voltage bits is set.  also !CB_CBARD doesn't mean CB_16BITCARD.  there is
  CB_NOTACARD as well, so make an explicit check for CB_16BITCARD.

- for TI bridges: disable IRQs during power-on.  in all-serial and tied
  interrupt mode the interrupts are always disabled for single-slot
  controllers.  for two-slot contollers the disabling is only done when the
  other slot is empty.  to force disabling there is a new module parameter
  now: pwr_irqs_off=Y (which is a regression for working setups.  that's
  why it's an option, only use when required)

- modparm to disable ISA interrupt probing (isa_probe, defaults to on)

- remove unneeded code/cleanups (ie.  merge yenta_events() into
  yenta_interrupts())

Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Daniel Ritz
2005-06-23 00:10:12 -07:00
committed by Linus Torvalds
parent 7007cab531
commit fa912bcb06
4 changed files with 223 additions and 23 deletions
+167
View File
@@ -611,6 +611,170 @@ out:
}
}
/* Returns true value if the second slot of a two-slot controller is empty */
static int ti12xx_2nd_slot_empty(struct yenta_socket *socket)
{
struct pci_dev *func;
struct yenta_socket *slot2;
int devfn;
unsigned int state;
int ret = 1;
/* catch the two-slot controllers */
switch (socket->dev->device) {
case PCI_DEVICE_ID_TI_1220:
case PCI_DEVICE_ID_TI_1221:
case PCI_DEVICE_ID_TI_1225:
case PCI_DEVICE_ID_TI_1251A:
case PCI_DEVICE_ID_TI_1251B:
case PCI_DEVICE_ID_TI_1420:
case PCI_DEVICE_ID_TI_1450:
case PCI_DEVICE_ID_TI_1451A:
case PCI_DEVICE_ID_TI_1520:
case PCI_DEVICE_ID_TI_1620:
case PCI_DEVICE_ID_TI_4520:
case PCI_DEVICE_ID_TI_4450:
case PCI_DEVICE_ID_TI_4451:
/*
* there are way more, but they need to be added in yenta_socket.c
* and pci_ids.h first anyway.
*/
break;
/* single-slot controllers have the 2nd slot empty always :) */
default:
return 1;
}
/* get other slot */
devfn = socket->dev->devfn & ~0x07;
func = pci_get_slot(socket->dev->bus,
(socket->dev->devfn & 0x07) ? devfn : devfn | 0x01);
if (!func)
return 1;
slot2 = pci_get_drvdata(func);
if (!slot2)
goto out;
/* check state */
yenta_get_status(&socket->socket, &state);
if (state & SS_DETECT) {
ret = 0;
goto out;
}
out:
pci_dev_put(func);
return ret;
}
/*
* TI specifiy parts for the power hook.
*
* some TI's with some CB's produces interrupt storm on power on. it has been
* seen with atheros wlan cards on TI1225 and TI1410. solution is simply to
* disable any CB interrupts during this time.
*/
static int ti12xx_power_hook(struct pcmcia_socket *sock, int operation)
{
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
u32 mfunc, devctl, sysctl;
u8 gpio3;
/* only POWER_PRE and POWER_POST are interesting */
if ((operation != HOOK_POWER_PRE) && (operation != HOOK_POWER_POST))
return 0;
devctl = config_readb(socket, TI113X_DEVICE_CONTROL);
sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
mfunc = config_readl(socket, TI122X_MFUNC);
/*
* all serial/tied: only disable when modparm set. always doing it
* would mean a regression for working setups 'cos it disables the
* interrupts for both both slots on 2-slot controllers
* (and users of single slot controllers where it's save have to
* live with setting the modparm, most don't have to anyway)
*/
if (((devctl & TI113X_DCR_IMODE_MASK) == TI12XX_DCR_IMODE_ALL_SERIAL) &&
(pwr_irqs_off || ti12xx_2nd_slot_empty(socket))) {
switch (socket->dev->device) {
case PCI_DEVICE_ID_TI_1250:
case PCI_DEVICE_ID_TI_1251A:
case PCI_DEVICE_ID_TI_1251B:
case PCI_DEVICE_ID_TI_1450:
case PCI_DEVICE_ID_TI_1451A:
case PCI_DEVICE_ID_TI_4450:
case PCI_DEVICE_ID_TI_4451:
/* these chips have no IRQSER setting in MFUNC3 */
break;
default:
if (operation == HOOK_POWER_PRE)
mfunc = (mfunc & ~TI122X_MFUNC3_MASK);
else
mfunc = (mfunc & ~TI122X_MFUNC3_MASK) | TI122X_MFUNC3_IRQSER;
}
return 0;
}
/* do the job differently for func0/1 */
if ((PCI_FUNC(socket->dev->devfn) == 0) ||
((sysctl & TI122X_SCR_INTRTIE) &&
(pwr_irqs_off || ti12xx_2nd_slot_empty(socket)))) {
/* some bridges are different */
switch (socket->dev->device) {
case PCI_DEVICE_ID_TI_1250:
case PCI_DEVICE_ID_TI_1251A:
case PCI_DEVICE_ID_TI_1251B:
case PCI_DEVICE_ID_TI_1450:
/* those oldies use gpio3 for INTA */
gpio3 = config_readb(socket, TI1250_GPIO3_CONTROL);
if (operation == HOOK_POWER_PRE)
gpio3 = (gpio3 & ~TI1250_GPIO_MODE_MASK) | 0x40;
else
gpio3 &= ~TI1250_GPIO_MODE_MASK;
config_writeb(socket, TI1250_GPIO3_CONTROL, gpio3);
break;
default:
/* all new bridges are the same */
if (operation == HOOK_POWER_PRE)
mfunc &= ~TI122X_MFUNC0_MASK;
else
mfunc |= TI122X_MFUNC0_INTA;
config_writel(socket, TI122X_MFUNC, mfunc);
}
} else {
switch (socket->dev->device) {
case PCI_DEVICE_ID_TI_1251A:
case PCI_DEVICE_ID_TI_1251B:
case PCI_DEVICE_ID_TI_1450:
/* those have INTA elsewhere and INTB in MFUNC0 */
if (operation == HOOK_POWER_PRE)
mfunc &= ~TI122X_MFUNC0_MASK;
else
mfunc |= TI125X_MFUNC0_INTB;
config_writel(socket, TI122X_MFUNC, mfunc);
break;
default:
/* all new bridges are the same */
if (operation == HOOK_POWER_PRE)
mfunc &= ~TI122X_MFUNC1_MASK;
else
mfunc |= TI122X_MFUNC1_INTB;
config_writel(socket, TI122X_MFUNC, mfunc);
}
}
return 0;
}
static int ti12xx_override(struct yenta_socket *socket)
{
u32 val, val_orig;
@@ -654,6 +818,9 @@ static int ti12xx_override(struct yenta_socket *socket)
else
ti12xx_irqroute_func1(socket);
/* install power hook */
socket->socket.power_hook = ti12xx_power_hook;
return ti_override(socket);
}