Skip to content

Commit

Permalink
[PATCH] yenta: auto-tune EnE bridges for CardBus cards
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: Linus Torvalds <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Dominik Brodowski <[email protected]>
  • Loading branch information
dr-itz authored and Dominik Brodowski committed Sep 26, 2005
1 parent 8ddec74 commit 8c3520d
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 15 deletions.
5 changes: 5 additions & 0 deletions drivers/pcmcia/cardbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
86 changes: 76 additions & 10 deletions drivers/pcmcia/ti113x.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 */

15 changes: 11 additions & 4 deletions drivers/pcmcia/yenta_socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,7 @@ enum {
CARDBUS_TYPE_TOPIC95,
CARDBUS_TYPE_TOPIC97,
CARDBUS_TYPE_O2MICRO,
CARDBUS_TYPE_ENE,
};

/*
Expand Down Expand Up @@ -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,
},
};


Expand Down Expand Up @@ -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),
Expand Down
5 changes: 5 additions & 0 deletions include/linux/pci_ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion include/pcmcia/ss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */

Expand Down

0 comments on commit 8c3520d

Please sign in to comment.