[PATCH] yenta: auto-tune EnE bridges for CardBus cards
Echo Audio cardbus products are known to be incompatible with EnE bridges. in order to maybe solve the problem a EnE specific test bit has to be set, another cleared...but other setups have a good chance to break when just forcing the bits. so do the whole thingy automatically. The patch adds a hook in cb_alloc() that allows special tuning for the different chipsets. for ene just match the Echo products and set/clear the test bits, defaults to do the same thing as w/o the patch to not break working setups. Signed-off-by: Daniel Ritz <daniel.ritz@gmx.ch> Cc: Linus Torvalds <torvalds@osdl.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
This commit is contained in:
parent
8ddec7460d
commit
8c3520d4eb
5 changed files with 105 additions and 15 deletions
|
@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s)
|
|||
pci_bus_size_bridges(bus);
|
||||
pci_bus_assign_resources(bus);
|
||||
cardbus_assign_irqs(bus, s->pci_irq);
|
||||
|
||||
/* socket specific tune function */
|
||||
if (s->tune_bridge)
|
||||
s->tune_bridge(s, bus);
|
||||
|
||||
pci_enable_bridges(bus);
|
||||
pci_bus_add_devices(bus);
|
||||
|
||||
|
|
|
@ -153,6 +153,12 @@
|
|||
/* EnE test register */
|
||||
#define ENE_TEST_C9 0xc9 /* 8bit */
|
||||
#define ENE_TEST_C9_TLTENABLE 0x02
|
||||
#define ENE_TEST_C9_PFENABLE_F0 0x04
|
||||
#define ENE_TEST_C9_PFENABLE_F1 0x08
|
||||
#define ENE_TEST_C9_PFENABLE (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0)
|
||||
#define ENE_TEST_C9_WPDISALBLE_F0 0x40
|
||||
#define ENE_TEST_C9_WPDISALBLE_F1 0x80
|
||||
#define ENE_TEST_C9_WPDISALBLE (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1)
|
||||
|
||||
/*
|
||||
* Texas Instruments CardBus controller overrides.
|
||||
|
@ -790,16 +796,6 @@ static int ti12xx_override(struct yenta_socket *socket)
|
|||
if (val_orig != val)
|
||||
config_writel(socket, TI113X_SYSTEM_CONTROL, val);
|
||||
|
||||
/*
|
||||
* for EnE bridges only: clear testbit TLTEnable. this makes the
|
||||
* RME Hammerfall DSP sound card working.
|
||||
*/
|
||||
if (socket->dev->vendor == PCI_VENDOR_ID_ENE) {
|
||||
u8 test_c9 = config_readb(socket, ENE_TEST_C9);
|
||||
test_c9 &= ~ENE_TEST_C9_TLTENABLE;
|
||||
config_writeb(socket, ENE_TEST_C9, test_c9);
|
||||
}
|
||||
|
||||
/*
|
||||
* Yenta expects controllers to use CSCINT to route
|
||||
* CSC interrupts to PCI rather than INTVAL.
|
||||
|
@ -841,5 +837,75 @@ static int ti1250_override(struct yenta_socket *socket)
|
|||
return ti12xx_override(socket);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* EnE specific part. EnE bridges are register compatible with TI bridges but
|
||||
* have their own test registers and more important their own little problems.
|
||||
* Some fixup code to make everybody happy (TM).
|
||||
*/
|
||||
|
||||
/**
|
||||
* set/clear various test bits:
|
||||
* Defaults to clear the bit.
|
||||
* - mask (u8) defines what bits to change
|
||||
* - bits (u8) is the values to change them to
|
||||
* -> it's
|
||||
* current = (current & ~mask) | bits
|
||||
*/
|
||||
/* pci ids of devices that wants to have the bit set */
|
||||
#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) { \
|
||||
.vendor = _vend, \
|
||||
.device = _dev, \
|
||||
.subvendor = _subvend, \
|
||||
.subdevice = _subdev, \
|
||||
.driver_data = ((mask) << 8 | (bits)), \
|
||||
}
|
||||
static struct pci_device_id ene_tune_tbl[] = {
|
||||
/* Echo Audio products based on motorola DSP56301 and DSP56361 */
|
||||
DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID,
|
||||
ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
|
||||
DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID,
|
||||
ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE),
|
||||
|
||||
{}
|
||||
};
|
||||
|
||||
static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus)
|
||||
{
|
||||
struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket);
|
||||
struct pci_dev *dev;
|
||||
struct pci_device_id *id = NULL;
|
||||
u8 test_c9, old_c9, mask, bits;
|
||||
|
||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
||||
id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev);
|
||||
if (id)
|
||||
break;
|
||||
}
|
||||
|
||||
test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9);
|
||||
if (id) {
|
||||
mask = (id->driver_data >> 8) & 0xFF;
|
||||
bits = id->driver_data & 0xFF;
|
||||
|
||||
test_c9 = (test_c9 & ~mask) | bits;
|
||||
}
|
||||
else
|
||||
/* default to clear TLTEnable bit, old behaviour */
|
||||
test_c9 &= ~ENE_TEST_C9_TLTENABLE;
|
||||
|
||||
printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9);
|
||||
config_writeb(socket, ENE_TEST_C9, test_c9);
|
||||
}
|
||||
|
||||
|
||||
static int ene_override(struct yenta_socket *socket)
|
||||
{
|
||||
/* install tune_bridge() function */
|
||||
socket->socket.tune_bridge = ene_tune_bridge;
|
||||
|
||||
return ti1250_override(socket);
|
||||
}
|
||||
|
||||
#endif /* _LINUX_TI113X_H */
|
||||
|
||||
|
|
|
@ -819,6 +819,7 @@ enum {
|
|||
CARDBUS_TYPE_TOPIC95,
|
||||
CARDBUS_TYPE_TOPIC97,
|
||||
CARDBUS_TYPE_O2MICRO,
|
||||
CARDBUS_TYPE_ENE,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -865,6 +866,12 @@ static struct cardbus_type cardbus_type[] = {
|
|||
.override = o2micro_override,
|
||||
.restore_state = o2micro_restore_state,
|
||||
},
|
||||
[CARDBUS_TYPE_ENE] = {
|
||||
.override = ene_override,
|
||||
.save_state = ti_save_state,
|
||||
.restore_state = ti_restore_state,
|
||||
.sock_init = ti_init,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
@ -1265,10 +1272,10 @@ static struct pci_device_id yenta_table [] = {
|
|||
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250),
|
||||
CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250),
|
||||
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE),
|
||||
CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE),
|
||||
|
||||
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH),
|
||||
CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH),
|
||||
|
|
|
@ -2187,7 +2187,12 @@
|
|||
#define PCI_DEVICE_ID_ENE_1211 0x1211
|
||||
#define PCI_DEVICE_ID_ENE_1225 0x1225
|
||||
#define PCI_DEVICE_ID_ENE_1410 0x1410
|
||||
#define PCI_DEVICE_ID_ENE_710 0x1411
|
||||
#define PCI_DEVICE_ID_ENE_712 0x1412
|
||||
#define PCI_DEVICE_ID_ENE_1420 0x1420
|
||||
#define PCI_DEVICE_ID_ENE_720 0x1421
|
||||
#define PCI_DEVICE_ID_ENE_722 0x1422
|
||||
|
||||
#define PCI_VENDOR_ID_CHELSIO 0x1425
|
||||
|
||||
#define PCI_VENDOR_ID_MIPS 0x153f
|
||||
|
|
|
@ -21,6 +21,9 @@
|
|||
#include <pcmcia/cs_types.h>
|
||||
#include <pcmcia/cs.h>
|
||||
#include <pcmcia/bulkmem.h>
|
||||
#ifdef CONFIG_CARDBUS
|
||||
#include <linux/pci.h>
|
||||
#endif
|
||||
|
||||
/* Definitions for card status flags for GetStatus */
|
||||
#define SS_WRPROT 0x0001
|
||||
|
@ -233,7 +236,11 @@ struct pcmcia_socket {
|
|||
|
||||
/* so is power hook */
|
||||
int (*power_hook)(struct pcmcia_socket *sock, int operation);
|
||||
|
||||
#ifdef CONFIG_CARDBUS
|
||||
/* allows tuning the CB bridge before loading driver for the CB card */
|
||||
void (*tune_bridge)(struct pcmcia_socket *sock, struct pci_bus *bus);
|
||||
#endif
|
||||
|
||||
/* state thread */
|
||||
struct semaphore skt_sem; /* protects socket h/w state */
|
||||
|
||||
|
|
Loading…
Reference in a new issue