diff options
author | Sergei Shtylyov <sshtylyov@ru.mvista.com> | 2007-09-11 16:28:35 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-09-11 16:28:35 -0400 |
commit | 7293136810936bbde403bcb67ac1b4dbae4dd790 (patch) | |
tree | bdbb37d76378bd9e96ef716130c253211ea0c46d /drivers/ide/pci/hpt366.c | |
parent | 35198234a26fdc0f858774e3ba143796323059a0 (diff) |
hpt366: fix PCI clock detection for HPT374 (take 4)
HPT374 BIOS seems to only save f_CNT register value for the function #0 before
re-tuning DPLL (that causes the driver to report obviously distorted f_CNT for
the function #1) -- fix this by always reading the saved f_CNT register value
from the function #0 in the driver's init_chipset() method.
While at it, introduce 'chip_type' for holding the 'struct hpt_info' field
of the same name and replace the structure assignment with memcpy()...
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/hpt366.c')
-rw-r--r-- | drivers/ide/pci/hpt366.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 2cd74c345a6c..f87eec970574 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/ide/pci/hpt366.c Version 1.10 Jun 29, 2007 | 2 | * linux/drivers/ide/pci/hpt366.c Version 1.11 Aug 11, 2007 |
3 | * | 3 | * |
4 | * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> | 4 | * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> |
5 | * Portions Copyright (C) 2001 Sun Microsystems, Inc. | 5 | * Portions Copyright (C) 2001 Sun Microsystems, Inc. |
@@ -68,7 +68,8 @@ | |||
68 | * HPT37x chip family; save space by introducing the separate transfer mode | 68 | * HPT37x chip family; save space by introducing the separate transfer mode |
69 | * table in which the mode lookup is done | 69 | * table in which the mode lookup is done |
70 | * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives | 70 | * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives |
71 | * the wrong PCI frequency since DPLL has already been calibrated by BIOS | 71 | * the wrong PCI frequency since DPLL has already been calibrated by BIOS; |
72 | * read it only from the function 0 of HPT374 chips | ||
72 | * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, | 73 | * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, |
73 | * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead | 74 | * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead |
74 | * - pass to init_chipset() handlers a copy of the IDE PCI device structure as | 75 | * - pass to init_chipset() handlers a copy of the IDE PCI device structure as |
@@ -981,6 +982,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
981 | struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); | 982 | struct hpt_info *info = kmalloc(sizeof(struct hpt_info), GFP_KERNEL); |
982 | unsigned long io_base = pci_resource_start(dev, 4); | 983 | unsigned long io_base = pci_resource_start(dev, 4); |
983 | u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ | 984 | u8 pci_clk, dpll_clk = 0; /* PCI and DPLL clock in MHz */ |
985 | u8 chip_type; | ||
984 | enum ata_clock clock; | 986 | enum ata_clock clock; |
985 | 987 | ||
986 | if (info == NULL) { | 988 | if (info == NULL) { |
@@ -992,7 +994,8 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
992 | * Copy everything from a static "template" structure | 994 | * Copy everything from a static "template" structure |
993 | * to just allocated per-chip hpt_info structure. | 995 | * to just allocated per-chip hpt_info structure. |
994 | */ | 996 | */ |
995 | *info = *(struct hpt_info *)pci_get_drvdata(dev); | 997 | memcpy(info, pci_get_drvdata(dev), sizeof(struct hpt_info)); |
998 | chip_type = info->chip_type; | ||
996 | 999 | ||
997 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); | 1000 | pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); |
998 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); | 1001 | pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x78); |
@@ -1002,7 +1005,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1002 | /* | 1005 | /* |
1003 | * First, try to estimate the PCI clock frequency... | 1006 | * First, try to estimate the PCI clock frequency... |
1004 | */ | 1007 | */ |
1005 | if (info->chip_type >= HPT370) { | 1008 | if (chip_type >= HPT370) { |
1006 | u8 scr1 = 0; | 1009 | u8 scr1 = 0; |
1007 | u16 f_cnt = 0; | 1010 | u16 f_cnt = 0; |
1008 | u32 temp = 0; | 1011 | u32 temp = 0; |
@@ -1016,7 +1019,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1016 | * HighPoint does this for HPT372A. | 1019 | * HighPoint does this for HPT372A. |
1017 | * NOTE: This register is only writeable via I/O space. | 1020 | * NOTE: This register is only writeable via I/O space. |
1018 | */ | 1021 | */ |
1019 | if (info->chip_type == HPT372A) | 1022 | if (chip_type == HPT372A) |
1020 | outb(0x0e, io_base + 0x9c); | 1023 | outb(0x0e, io_base + 0x9c); |
1021 | 1024 | ||
1022 | /* | 1025 | /* |
@@ -1034,13 +1037,28 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1034 | * First try reading the register in which the HighPoint BIOS | 1037 | * First try reading the register in which the HighPoint BIOS |
1035 | * saves f_CNT value before reprogramming the DPLL from its | 1038 | * saves f_CNT value before reprogramming the DPLL from its |
1036 | * default setting (which differs for the various chips). | 1039 | * default setting (which differs for the various chips). |
1037 | * NOTE: This register is only accessible via I/O space. | ||
1038 | * | 1040 | * |
1039 | * In case the signature check fails, we'll have to resort to | 1041 | * NOTE: This register is only accessible via I/O space; |
1040 | * reading the f_CNT register itself in hopes that nobody has | 1042 | * HPT374 BIOS only saves it for the function 0, so we have to |
1041 | * touched the DPLL yet... | 1043 | * always read it from there -- no need to check the result of |
1044 | * pci_get_slot() for the function 0 as the whole device has | ||
1045 | * been already "pinned" (via function 1) in init_setup_hpt374() | ||
1046 | */ | ||
1047 | if (chip_type == HPT374 && (PCI_FUNC(dev->devfn) & 1)) { | ||
1048 | struct pci_dev *dev1 = pci_get_slot(dev->bus, | ||
1049 | dev->devfn - 1); | ||
1050 | unsigned long io_base = pci_resource_start(dev1, 4); | ||
1051 | |||
1052 | temp = inl(io_base + 0x90); | ||
1053 | pci_dev_put(dev1); | ||
1054 | } else | ||
1055 | temp = inl(io_base + 0x90); | ||
1056 | |||
1057 | /* | ||
1058 | * In case the signature check fails, we'll have to | ||
1059 | * resort to reading the f_CNT register itself in hopes | ||
1060 | * that nobody has touched the DPLL yet... | ||
1042 | */ | 1061 | */ |
1043 | temp = inl(io_base + 0x90); | ||
1044 | if ((temp & 0xFFFFF000) != 0xABCDE000) { | 1062 | if ((temp & 0xFFFFF000) != 0xABCDE000) { |
1045 | int i; | 1063 | int i; |
1046 | 1064 | ||
@@ -1120,7 +1138,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1120 | * We also don't like using the DPLL because this causes glitches | 1138 | * We also don't like using the DPLL because this causes glitches |
1121 | * on PRST-/SRST- when the state engine gets reset... | 1139 | * on PRST-/SRST- when the state engine gets reset... |
1122 | */ | 1140 | */ |
1123 | if (info->chip_type >= HPT374 || info->settings[clock] == NULL) { | 1141 | if (chip_type >= HPT374 || info->settings[clock] == NULL) { |
1124 | u16 f_low, delta = pci_clk < 50 ? 2 : 4; | 1142 | u16 f_low, delta = pci_clk < 50 ? 2 : 4; |
1125 | int adjust; | 1143 | int adjust; |
1126 | 1144 | ||
@@ -1190,7 +1208,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1190 | /* Point to this chip's own instance of the hpt_info structure. */ | 1208 | /* Point to this chip's own instance of the hpt_info structure. */ |
1191 | pci_set_drvdata(dev, info); | 1209 | pci_set_drvdata(dev, info); |
1192 | 1210 | ||
1193 | if (info->chip_type >= HPT370) { | 1211 | if (chip_type >= HPT370) { |
1194 | u8 mcr1, mcr4; | 1212 | u8 mcr1, mcr4; |
1195 | 1213 | ||
1196 | /* | 1214 | /* |
@@ -1209,7 +1227,7 @@ static unsigned int __devinit init_chipset_hpt366(struct pci_dev *dev, const cha | |||
1209 | * the MISC. register to stretch the UltraDMA Tss timing. | 1227 | * the MISC. register to stretch the UltraDMA Tss timing. |
1210 | * NOTE: This register is only writeable via I/O space. | 1228 | * NOTE: This register is only writeable via I/O space. |
1211 | */ | 1229 | */ |
1212 | if (info->chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) | 1230 | if (chip_type == HPT371N && clock == ATA_CLOCK_66MHZ) |
1213 | 1231 | ||
1214 | outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); | 1232 | outb(inb(io_base + 0x9c) | 0x04, io_base + 0x9c); |
1215 | 1233 | ||