diff options
| author | Daniel Ritz <daniel.ritz@gmx.ch> | 2005-08-22 01:29:26 -0400 |
|---|---|---|
| committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2005-09-26 07:09:20 -0400 |
| commit | 8c3520d4eb3b1bbf2e45fbae8dcfb8db06d5e775 (patch) | |
| tree | df9b4f49e8f9ffa34657776be458fbd124b2e87b | |
| parent | 8ddec7460d2f5db3ac35812c03676b1473d1d668 (diff) | |
[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>
| -rw-r--r-- | drivers/pcmcia/cardbus.c | 5 | ||||
| -rw-r--r-- | drivers/pcmcia/ti113x.h | 86 | ||||
| -rw-r--r-- | drivers/pcmcia/yenta_socket.c | 15 | ||||
| -rw-r--r-- | include/linux/pci_ids.h | 5 | ||||
| -rw-r--r-- | include/pcmcia/ss.h | 9 |
5 files changed, 105 insertions, 15 deletions
diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 1d755e20880c..3f6d51d11374 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c | |||
| @@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s) | |||
| 228 | pci_bus_size_bridges(bus); | 228 | pci_bus_size_bridges(bus); |
| 229 | pci_bus_assign_resources(bus); | 229 | pci_bus_assign_resources(bus); |
| 230 | cardbus_assign_irqs(bus, s->pci_irq); | 230 | cardbus_assign_irqs(bus, s->pci_irq); |
| 231 | |||
| 232 | /* socket specific tune function */ | ||
| 233 | if (s->tune_bridge) | ||
| 234 | s->tune_bridge(s, bus); | ||
| 235 | |||
| 231 | pci_enable_bridges(bus); | 236 | pci_enable_bridges(bus); |
| 232 | pci_bus_add_devices(bus); | 237 | pci_bus_add_devices(bus); |
| 233 | 238 | ||
diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index fbe233e19ceb..d319f2e7d053 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h | |||
| @@ -153,6 +153,12 @@ | |||
| 153 | /* EnE test register */ | 153 | /* EnE test register */ |
| 154 | #define ENE_TEST_C9 0xc9 /* 8bit */ | 154 | #define ENE_TEST_C9 0xc9 /* 8bit */ |
| 155 | #define ENE_TEST_C9_TLTENABLE 0x02 | 155 | #define ENE_TEST_C9_TLTENABLE 0x02 |
| 156 | #define ENE_TEST_C9_PFENABLE_F0 0x04 | ||
| 157 | #define ENE_TEST_C9_PFENABLE_F1 0x08 | ||
| 158 | #define ENE_TEST_C9_PFENABLE (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0) | ||
| 159 | #define ENE_TEST_C9_WPDISALBLE_F0 0x40 | ||
| 160 | #define ENE_TEST_C9_WPDISALBLE_F1 0x80 | ||
| 161 | #define ENE_TEST_C9_WPDISALBLE (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1) | ||
| 156 | 162 | ||
| 157 | /* | 163 | /* |
| 158 | * Texas Instruments CardBus controller overrides. | 164 | * Texas Instruments CardBus controller overrides. |
| @@ -791,16 +797,6 @@ static int ti12xx_override(struct yenta_socket *socket) | |||
| 791 | config_writel(socket, TI113X_SYSTEM_CONTROL, val); | 797 | config_writel(socket, TI113X_SYSTEM_CONTROL, val); |
| 792 | 798 | ||
| 793 | /* | 799 | /* |
| 794 | * for EnE bridges only: clear testbit TLTEnable. this makes the | ||
| 795 | * RME Hammerfall DSP sound card working. | ||
| 796 | */ | ||
| 797 | if (socket->dev->vendor == PCI_VENDOR_ID_ENE) { | ||
| 798 | u8 test_c9 = config_readb(socket, ENE_TEST_C9); | ||
| 799 | test_c9 &= ~ENE_TEST_C9_TLTENABLE; | ||
| 800 | config_writeb(socket, ENE_TEST_C9, test_c9); | ||
| 801 | } | ||
| 802 | |||
| 803 | /* | ||
| 804 | * Yenta expects controllers to use CSCINT to route | 800 | * Yenta expects controllers to use CSCINT to route |
| 805 | * CSC interrupts to PCI rather than INTVAL. | 801 | * CSC interrupts to PCI rather than INTVAL. |
| 806 | */ | 802 | */ |
| @@ -841,5 +837,75 @@ static int ti1250_override(struct yenta_socket *socket) | |||
| 841 | return ti12xx_override(socket); | 837 | return ti12xx_override(socket); |
| 842 | } | 838 | } |
| 843 | 839 | ||
| 840 | |||
| 841 | /** | ||
| 842 | * EnE specific part. EnE bridges are register compatible with TI bridges but | ||
| 843 | * have their own test registers and more important their own little problems. | ||
| 844 | * Some fixup code to make everybody happy (TM). | ||
| 845 | */ | ||
| 846 | |||
| 847 | /** | ||
| 848 | * set/clear various test bits: | ||
| 849 | * Defaults to clear the bit. | ||
| 850 | * - mask (u8) defines what bits to change | ||
| 851 | * - bits (u8) is the values to change them to | ||
| 852 | * -> it's | ||
| 853 | * current = (current & ~mask) | bits | ||
| 854 | */ | ||
| 855 | /* pci ids of devices that wants to have the bit set */ | ||
| 856 | #define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) { \ | ||
| 857 | .vendor = _vend, \ | ||
| 858 | .device = _dev, \ | ||
| 859 | .subvendor = _subvend, \ | ||
| 860 | .subdevice = _subdev, \ | ||
| 861 | .driver_data = ((mask) << 8 | (bits)), \ | ||
| 862 | } | ||
| 863 | static struct pci_device_id ene_tune_tbl[] = { | ||
| 864 | /* Echo Audio products based on motorola DSP56301 and DSP56361 */ | ||
| 865 | DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID, | ||
| 866 | ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), | ||
| 867 | DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID, | ||
| 868 | ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), | ||
| 869 | |||
| 870 | {} | ||
| 871 | }; | ||
| 872 | |||
| 873 | static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) | ||
| 874 | { | ||
| 875 | struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); | ||
| 876 | struct pci_dev *dev; | ||
| 877 | struct pci_device_id *id = NULL; | ||
| 878 | u8 test_c9, old_c9, mask, bits; | ||
| 879 | |||
| 880 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 881 | id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev); | ||
| 882 | if (id) | ||
| 883 | break; | ||
| 884 | } | ||
| 885 | |||
| 886 | test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9); | ||
| 887 | if (id) { | ||
| 888 | mask = (id->driver_data >> 8) & 0xFF; | ||
| 889 | bits = id->driver_data & 0xFF; | ||
| 890 | |||
| 891 | test_c9 = (test_c9 & ~mask) | bits; | ||
| 892 | } | ||
| 893 | else | ||
| 894 | /* default to clear TLTEnable bit, old behaviour */ | ||
| 895 | test_c9 &= ~ENE_TEST_C9_TLTENABLE; | ||
| 896 | |||
| 897 | printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9); | ||
| 898 | config_writeb(socket, ENE_TEST_C9, test_c9); | ||
| 899 | } | ||
| 900 | |||
| 901 | |||
| 902 | static int ene_override(struct yenta_socket *socket) | ||
| 903 | { | ||
| 904 | /* install tune_bridge() function */ | ||
| 905 | socket->socket.tune_bridge = ene_tune_bridge; | ||
| 906 | |||
| 907 | return ti1250_override(socket); | ||
| 908 | } | ||
| 909 | |||
| 844 | #endif /* _LINUX_TI113X_H */ | 910 | #endif /* _LINUX_TI113X_H */ |
| 845 | 911 | ||
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index ba4d78e5b121..fd2a6f892c41 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c | |||
| @@ -819,6 +819,7 @@ enum { | |||
| 819 | CARDBUS_TYPE_TOPIC95, | 819 | CARDBUS_TYPE_TOPIC95, |
| 820 | CARDBUS_TYPE_TOPIC97, | 820 | CARDBUS_TYPE_TOPIC97, |
| 821 | CARDBUS_TYPE_O2MICRO, | 821 | CARDBUS_TYPE_O2MICRO, |
| 822 | CARDBUS_TYPE_ENE, | ||
| 822 | }; | 823 | }; |
| 823 | 824 | ||
| 824 | /* | 825 | /* |
| @@ -865,6 +866,12 @@ static struct cardbus_type cardbus_type[] = { | |||
| 865 | .override = o2micro_override, | 866 | .override = o2micro_override, |
| 866 | .restore_state = o2micro_restore_state, | 867 | .restore_state = o2micro_restore_state, |
| 867 | }, | 868 | }, |
| 869 | [CARDBUS_TYPE_ENE] = { | ||
| 870 | .override = ene_override, | ||
| 871 | .save_state = ti_save_state, | ||
| 872 | .restore_state = ti_restore_state, | ||
| 873 | .sock_init = ti_init, | ||
| 874 | }, | ||
| 868 | }; | 875 | }; |
| 869 | 876 | ||
| 870 | 877 | ||
| @@ -1265,10 +1272,10 @@ static struct pci_device_id yenta_table [] = { | |||
| 1265 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), | 1272 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), |
| 1266 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), | 1273 | CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), |
| 1267 | 1274 | ||
| 1268 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX), | 1275 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), |
| 1269 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX), | 1276 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), |
| 1270 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250), | 1277 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), |
| 1271 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX), | 1278 | CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), |
| 1272 | 1279 | ||
| 1273 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), | 1280 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), |
| 1274 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), | 1281 | CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), |
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index b86a4b77007e..92efb2c767f9 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h | |||
| @@ -2187,7 +2187,12 @@ | |||
| 2187 | #define PCI_DEVICE_ID_ENE_1211 0x1211 | 2187 | #define PCI_DEVICE_ID_ENE_1211 0x1211 |
| 2188 | #define PCI_DEVICE_ID_ENE_1225 0x1225 | 2188 | #define PCI_DEVICE_ID_ENE_1225 0x1225 |
| 2189 | #define PCI_DEVICE_ID_ENE_1410 0x1410 | 2189 | #define PCI_DEVICE_ID_ENE_1410 0x1410 |
| 2190 | #define PCI_DEVICE_ID_ENE_710 0x1411 | ||
| 2191 | #define PCI_DEVICE_ID_ENE_712 0x1412 | ||
| 2190 | #define PCI_DEVICE_ID_ENE_1420 0x1420 | 2192 | #define PCI_DEVICE_ID_ENE_1420 0x1420 |
| 2193 | #define PCI_DEVICE_ID_ENE_720 0x1421 | ||
| 2194 | #define PCI_DEVICE_ID_ENE_722 0x1422 | ||
| 2195 | |||
| 2191 | #define PCI_VENDOR_ID_CHELSIO 0x1425 | 2196 | #define PCI_VENDOR_ID_CHELSIO 0x1425 |
| 2192 | 2197 | ||
| 2193 | #define PCI_VENDOR_ID_MIPS 0x153f | 2198 | #define PCI_VENDOR_ID_MIPS 0x153f |
diff --git a/include/pcmcia/ss.h b/include/pcmcia/ss.h index 0f7aacc33fe9..c8592c7e8eaa 100644 --- a/include/pcmcia/ss.h +++ b/include/pcmcia/ss.h | |||
| @@ -21,6 +21,9 @@ | |||
| 21 | #include <pcmcia/cs_types.h> | 21 | #include <pcmcia/cs_types.h> |
| 22 | #include <pcmcia/cs.h> | 22 | #include <pcmcia/cs.h> |
| 23 | #include <pcmcia/bulkmem.h> | 23 | #include <pcmcia/bulkmem.h> |
| 24 | #ifdef CONFIG_CARDBUS | ||
| 25 | #include <linux/pci.h> | ||
| 26 | #endif | ||
| 24 | 27 | ||
| 25 | /* Definitions for card status flags for GetStatus */ | 28 | /* Definitions for card status flags for GetStatus */ |
| 26 | #define SS_WRPROT 0x0001 | 29 | #define SS_WRPROT 0x0001 |
| @@ -233,7 +236,11 @@ struct pcmcia_socket { | |||
| 233 | 236 | ||
| 234 | /* so is power hook */ | 237 | /* so is power hook */ |
| 235 | int (*power_hook)(struct pcmcia_socket *sock, int operation); | 238 | int (*power_hook)(struct pcmcia_socket *sock, int operation); |
| 236 | 239 | #ifdef CONFIG_CARDBUS | |
| 240 | /* allows tuning the CB bridge before loading driver for the CB card */ | ||
| 241 | void (*tune_bridge)(struct pcmcia_socket *sock, struct pci_bus *bus); | ||
| 242 | #endif | ||
| 243 | |||
| 237 | /* state thread */ | 244 | /* state thread */ |
| 238 | struct semaphore skt_sem; /* protects socket h/w state */ | 245 | struct semaphore skt_sem; /* protects socket h/w state */ |
| 239 | 246 | ||
