[PATCH] ide: HPT3xx: fix PCI clock detection

Use the f_CNT value saved by the HighPoint BIOS if available as reading it
directly would give us a wrong PCI frequency after DPLL has already been
calibrated by BIOS.

Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Sergei Shtylyov and committed by
Linus Torvalds
26c068da 73d1dd93

+32 -14
+32 -14
drivers/ide/pci/hpt366.c
··· 70 * - fix/remove bad/unused timing tables and use one set of tables for the whole 71 * HPT37x chip family; save space by introducing the separate transfer mode 72 * table in which the mode lookup is done 73 * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, 74 * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead 75 * - pass to init_chipset() handlers a copy of the IDE PCI device structure as ··· 1012 struct hpt_info *info = ide_get_hwifdata(hwif); 1013 struct pci_dev *dev = hwif->pci_dev; 1014 int adjust, i; 1015 - u16 freq; 1016 - u32 pll; 1017 u8 reg5bh = 0, mcr1 = 0; 1018 1019 /* ··· 1027 pci_write_config_byte(dev, 0x5b, 0x23); 1028 1029 /* 1030 - * set up the PLL. we need to adjust it so that it's stable. 1031 - * freq = Tpll * 192 / Tpci 1032 * 1033 - * Todo. For non x86 should probably check the dword is 1034 - * set to 0xABCDExxx indicating the BIOS saved f_CNT 1035 */ 1036 - pci_read_config_word(dev, 0x78, &freq); 1037 - freq &= 0x1FF; 1038 - 1039 /* 1040 * HPT3xxN chips use different PCI clock information. 1041 * Currently we always set up the PLL for them. ··· 1116 info->flags |= PLL_MODE; 1117 1118 /* 1119 - * FIXME: make this work correctly, esp with 372N as per 1120 - * reference driver code. 1121 - * 1122 - * adjust PLL based upon PCI clock, enable it, and wait for 1123 - * stabilization. 1124 */ 1125 adjust = 0; 1126 freq = (pll < F_LOW_PCI_50) ? 2 : 4;
··· 70 * - fix/remove bad/unused timing tables and use one set of tables for the whole 71 * HPT37x chip family; save space by introducing the separate transfer mode 72 * table in which the mode lookup is done 73 + * - use f_CNT value saved by the HighPoint BIOS as reading it directly gives 74 + * the wrong PCI frequency since DPLL has already been calibrated by BIOS 75 * - fix the hotswap code: it caused RESET- to glitch when tristating the bus, 76 * and for HPT36x the obsolete HDIO_TRISTATE_HWIF handler was called instead 77 * - pass to init_chipset() handlers a copy of the IDE PCI device structure as ··· 1010 struct hpt_info *info = ide_get_hwifdata(hwif); 1011 struct pci_dev *dev = hwif->pci_dev; 1012 int adjust, i; 1013 + u16 freq = 0; 1014 + u32 pll, temp = 0; 1015 u8 reg5bh = 0, mcr1 = 0; 1016 1017 /* ··· 1025 pci_write_config_byte(dev, 0x5b, 0x23); 1026 1027 /* 1028 + * We'll have to read f_CNT value in order to determine 1029 + * the PCI clock frequency according to the following ratio: 1030 * 1031 + * f_CNT = Fpci * 192 / Fdpll 1032 + * 1033 + * First try reading the register in which the HighPoint BIOS 1034 + * saves f_CNT value before reprogramming the DPLL from its 1035 + * default setting (which differs for the various chips). 1036 + * In case the signature check fails, we'll have to resort to 1037 + * reading the f_CNT register itself in hopes that nobody has 1038 + * touched the DPLL yet... 1039 */ 1040 + pci_read_config_dword(dev, 0x70, &temp); 1041 + if ((temp & 0xFFFFF000) != 0xABCDE000) { 1042 + int i; 1043 + 1044 + printk(KERN_WARNING "HPT37X: no clock data saved by BIOS\n"); 1045 + 1046 + /* Calculate the average value of f_CNT */ 1047 + for (temp = i = 0; i < 128; i++) { 1048 + pci_read_config_word(dev, 0x78, &freq); 1049 + temp += freq & 0x1ff; 1050 + mdelay(1); 1051 + } 1052 + freq = temp / 128; 1053 + } else 1054 + freq = temp & 0x1ff; 1055 + 1056 /* 1057 * HPT3xxN chips use different PCI clock information. 1058 * Currently we always set up the PLL for them. ··· 1095 info->flags |= PLL_MODE; 1096 1097 /* 1098 + * Adjust the PLL based upon the PCI clock, enable it, and 1099 + * wait for stabilization... 1100 */ 1101 adjust = 0; 1102 freq = (pll < F_LOW_PCI_50) ? 2 : 4;