18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * IDE Chipset driver for the Compaq TriFlex IDE controller. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Known to work with the Compaq Workstation 5x00 series. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 2002 Hewlett-Packard Development Group, L.P. 88c2ecf20Sopenharmony_ci * Author: Torben Mathiasen <torben.mathiasen@hp.com> 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Loosely based on the piix & svwks drivers. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Documentation: 138c2ecf20Sopenharmony_ci * Not publicly available. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <linux/types.h> 178c2ecf20Sopenharmony_ci#include <linux/module.h> 188c2ecf20Sopenharmony_ci#include <linux/kernel.h> 198c2ecf20Sopenharmony_ci#include <linux/pci.h> 208c2ecf20Sopenharmony_ci#include <linux/ide.h> 218c2ecf20Sopenharmony_ci#include <linux/init.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define DRV_NAME "triflex" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic void triflex_set_mode(ide_hwif_t *hwif, ide_drive_t *drive) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci struct pci_dev *dev = to_pci_dev(hwif->dev); 288c2ecf20Sopenharmony_ci u32 triflex_timings = 0; 298c2ecf20Sopenharmony_ci u16 timing = 0; 308c2ecf20Sopenharmony_ci u8 channel_offset = hwif->channel ? 0x74 : 0x70, unit = drive->dn & 1; 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci pci_read_config_dword(dev, channel_offset, &triflex_timings); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci switch (drive->dma_mode) { 358c2ecf20Sopenharmony_ci case XFER_MW_DMA_2: 368c2ecf20Sopenharmony_ci timing = 0x0103; 378c2ecf20Sopenharmony_ci break; 388c2ecf20Sopenharmony_ci case XFER_MW_DMA_1: 398c2ecf20Sopenharmony_ci timing = 0x0203; 408c2ecf20Sopenharmony_ci break; 418c2ecf20Sopenharmony_ci case XFER_MW_DMA_0: 428c2ecf20Sopenharmony_ci timing = 0x0808; 438c2ecf20Sopenharmony_ci break; 448c2ecf20Sopenharmony_ci case XFER_SW_DMA_2: 458c2ecf20Sopenharmony_ci case XFER_SW_DMA_1: 468c2ecf20Sopenharmony_ci case XFER_SW_DMA_0: 478c2ecf20Sopenharmony_ci timing = 0x0f0f; 488c2ecf20Sopenharmony_ci break; 498c2ecf20Sopenharmony_ci case XFER_PIO_4: 508c2ecf20Sopenharmony_ci timing = 0x0202; 518c2ecf20Sopenharmony_ci break; 528c2ecf20Sopenharmony_ci case XFER_PIO_3: 538c2ecf20Sopenharmony_ci timing = 0x0204; 548c2ecf20Sopenharmony_ci break; 558c2ecf20Sopenharmony_ci case XFER_PIO_2: 568c2ecf20Sopenharmony_ci timing = 0x0404; 578c2ecf20Sopenharmony_ci break; 588c2ecf20Sopenharmony_ci case XFER_PIO_1: 598c2ecf20Sopenharmony_ci timing = 0x0508; 608c2ecf20Sopenharmony_ci break; 618c2ecf20Sopenharmony_ci case XFER_PIO_0: 628c2ecf20Sopenharmony_ci timing = 0x0808; 638c2ecf20Sopenharmony_ci break; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci triflex_timings &= ~(0xFFFF << (16 * unit)); 678c2ecf20Sopenharmony_ci triflex_timings |= (timing << (16 * unit)); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci pci_write_config_dword(dev, channel_offset, triflex_timings); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic void triflex_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci drive->dma_mode = drive->pio_mode; 758c2ecf20Sopenharmony_ci triflex_set_mode(hwif, drive); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistatic const struct ide_port_ops triflex_port_ops = { 798c2ecf20Sopenharmony_ci .set_pio_mode = triflex_set_pio_mode, 808c2ecf20Sopenharmony_ci .set_dma_mode = triflex_set_mode, 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic const struct ide_port_info triflex_device = { 848c2ecf20Sopenharmony_ci .name = DRV_NAME, 858c2ecf20Sopenharmony_ci .enablebits = {{0x80, 0x01, 0x01}, {0x80, 0x02, 0x02}}, 868c2ecf20Sopenharmony_ci .port_ops = &triflex_port_ops, 878c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 888c2ecf20Sopenharmony_ci .swdma_mask = ATA_SWDMA2, 898c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 908c2ecf20Sopenharmony_ci}; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci return ide_pci_init_one(dev, &triflex_device, NULL); 958c2ecf20Sopenharmony_ci} 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_cistatic const struct pci_device_id triflex_pci_tbl[] = { 988c2ecf20Sopenharmony_ci { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), 0 }, 998c2ecf20Sopenharmony_ci { 0, }, 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, triflex_pci_tbl); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 1048c2ecf20Sopenharmony_cistatic int triflex_ide_pci_suspend(struct pci_dev *dev, pm_message_t state) 1058c2ecf20Sopenharmony_ci{ 1068c2ecf20Sopenharmony_ci /* 1078c2ecf20Sopenharmony_ci * We must not disable or powerdown the device. 1088c2ecf20Sopenharmony_ci * APM bios refuses to suspend if IDE is not accessible. 1098c2ecf20Sopenharmony_ci */ 1108c2ecf20Sopenharmony_ci pci_save_state(dev); 1118c2ecf20Sopenharmony_ci return 0; 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci#else 1148c2ecf20Sopenharmony_ci#define triflex_ide_pci_suspend NULL 1158c2ecf20Sopenharmony_ci#endif 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_cistatic struct pci_driver triflex_pci_driver = { 1188c2ecf20Sopenharmony_ci .name = "TRIFLEX_IDE", 1198c2ecf20Sopenharmony_ci .id_table = triflex_pci_tbl, 1208c2ecf20Sopenharmony_ci .probe = triflex_init_one, 1218c2ecf20Sopenharmony_ci .remove = ide_pci_remove, 1228c2ecf20Sopenharmony_ci .suspend = triflex_ide_pci_suspend, 1238c2ecf20Sopenharmony_ci .resume = ide_pci_resume, 1248c2ecf20Sopenharmony_ci}; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_cistatic int __init triflex_ide_init(void) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci return ide_pci_register_driver(&triflex_pci_driver); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void __exit triflex_ide_exit(void) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci pci_unregister_driver(&triflex_pci_driver); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cimodule_init(triflex_ide_init); 1378c2ecf20Sopenharmony_cimodule_exit(triflex_ide_exit); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ciMODULE_AUTHOR("Torben Mathiasen"); 1408c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI driver module for Compaq Triflex IDE"); 1418c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci 144