aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/ahci.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-11-19 02:03:44 -0500
committerJeff Garzik <jeff@garzik.org>2008-01-23 05:24:10 -0500
commit49f290903935612aadab3899a4aca884c1140348 (patch)
tree93e98e81a7d359c679ce081295d939be948c1c80 /drivers/ata/ahci.c
parent51dbd490614e6228e9b2b198bd4f5f76ef961059 (diff)
ahci: update PCS programming
For intel ones, ahci unconditionally OR'd 0xf to PCS. This isn't correct for the following cases. * ich6/7m's which only implement P0 and P2 (0xf works fine tho) * ich8/9's which have six ports and needs 0x3f to enable all ports This patch updates PCS programming such that... * port_map determined by ahci_save_initial_config() is OR'd instead of 0xf * PCS is updated only if necessary (there are turned off enable bits) port_map is determined from PORTS_IMPL PCI register which is implemented as write or write-once register. If the register isn't programmed, ahci automatically generates it from number of ports, which is good enough for PCS programming. ICH6/7M are probably the only ones where non-contiguous enable bits are necessary && PORTS_IMPL isn't programmed properly but they're proven to work reliably with 0xf anyway. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/ahci.c')
-rw-r--r--drivers/ata/ahci.c7
1 files changed, 5 insertions, 2 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 54f38c21dd95..ef5e6b6e6e69 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -1036,6 +1036,7 @@ static int ahci_deinit_port(struct ata_port *ap, const char **emsg)
1036static int ahci_reset_controller(struct ata_host *host) 1036static int ahci_reset_controller(struct ata_host *host)
1037{ 1037{
1038 struct pci_dev *pdev = to_pci_dev(host->dev); 1038 struct pci_dev *pdev = to_pci_dev(host->dev);
1039 struct ahci_host_priv *hpriv = host->private_data;
1039 void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; 1040 void __iomem *mmio = host->iomap[AHCI_PCI_BAR];
1040 u32 tmp; 1041 u32 tmp;
1041 1042
@@ -1078,8 +1079,10 @@ static int ahci_reset_controller(struct ata_host *host)
1078 1079
1079 /* configure PCS */ 1080 /* configure PCS */
1080 pci_read_config_word(pdev, 0x92, &tmp16); 1081 pci_read_config_word(pdev, 0x92, &tmp16);
1081 tmp16 |= 0xf; 1082 if ((tmp16 & hpriv->port_map) != hpriv->port_map) {
1082 pci_write_config_word(pdev, 0x92, tmp16); 1083 tmp16 |= hpriv->port_map;
1084 pci_write_config_word(pdev, 0x92, tmp16);
1085 }
1083 } 1086 }
1084 1087
1085 return 0; 1088 return 0;