18c2ecf20Sopenharmony_ci 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2006 Red Hat 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * May be copied or modified under the terms of the GNU General Public License 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/types.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/pci.h> 118c2ecf20Sopenharmony_ci#include <linux/ide.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#define DRV_NAME "jmicron" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_citypedef enum { 178c2ecf20Sopenharmony_ci PORT_PATA0 = 0, 188c2ecf20Sopenharmony_ci PORT_PATA1 = 1, 198c2ecf20Sopenharmony_ci PORT_SATA = 2, 208c2ecf20Sopenharmony_ci} port_type; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci/** 238c2ecf20Sopenharmony_ci * jmicron_cable_detect - cable detection 248c2ecf20Sopenharmony_ci * @hwif: IDE port 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * Returns the cable type. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic u8 jmicron_cable_detect(ide_hwif_t *hwif) 308c2ecf20Sopenharmony_ci{ 318c2ecf20Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(hwif->dev); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci u32 control; 348c2ecf20Sopenharmony_ci u32 control5; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci int port = hwif->channel; 378c2ecf20Sopenharmony_ci port_type port_map[2]; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, 0x40, &control); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* There are two basic mappings. One has the two SATA ports merged 428c2ecf20Sopenharmony_ci as master/slave and the secondary as PATA, the other has only the 438c2ecf20Sopenharmony_ci SATA port mapped */ 448c2ecf20Sopenharmony_ci if (control & (1 << 23)) { 458c2ecf20Sopenharmony_ci port_map[0] = PORT_SATA; 468c2ecf20Sopenharmony_ci port_map[1] = PORT_PATA0; 478c2ecf20Sopenharmony_ci } else { 488c2ecf20Sopenharmony_ci port_map[0] = PORT_SATA; 498c2ecf20Sopenharmony_ci port_map[1] = PORT_SATA; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci /* The 365/366 may have this bit set to map the second PATA port 538c2ecf20Sopenharmony_ci as the internal primary channel */ 548c2ecf20Sopenharmony_ci pci_read_config_dword(pdev, 0x80, &control5); 558c2ecf20Sopenharmony_ci if (control5 & (1<<24)) 568c2ecf20Sopenharmony_ci port_map[0] = PORT_PATA1; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* The two ports may then be logically swapped by the firmware */ 598c2ecf20Sopenharmony_ci if (control & (1 << 22)) 608c2ecf20Sopenharmony_ci port = port ^ 1; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci /* 638c2ecf20Sopenharmony_ci * Now we know which physical port we are talking about we can 648c2ecf20Sopenharmony_ci * actually do our cable checking etc. Thankfully we don't need 658c2ecf20Sopenharmony_ci * to do the plumbing for other cases. 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_ci switch (port_map[port]) { 688c2ecf20Sopenharmony_ci case PORT_PATA0: 698c2ecf20Sopenharmony_ci if (control & (1 << 3)) /* 40/80 pin primary */ 708c2ecf20Sopenharmony_ci return ATA_CBL_PATA40; 718c2ecf20Sopenharmony_ci return ATA_CBL_PATA80; 728c2ecf20Sopenharmony_ci case PORT_PATA1: 738c2ecf20Sopenharmony_ci if (control5 & (1 << 19)) /* 40/80 pin secondary */ 748c2ecf20Sopenharmony_ci return ATA_CBL_PATA40; 758c2ecf20Sopenharmony_ci return ATA_CBL_PATA80; 768c2ecf20Sopenharmony_ci case PORT_SATA: 778c2ecf20Sopenharmony_ci break; 788c2ecf20Sopenharmony_ci } 798c2ecf20Sopenharmony_ci /* Avoid bogus "control reaches end of non-void function" */ 808c2ecf20Sopenharmony_ci return ATA_CBL_PATA80; 818c2ecf20Sopenharmony_ci} 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic void jmicron_set_pio_mode(ide_hwif_t *hwif, ide_drive_t *drive) 848c2ecf20Sopenharmony_ci{ 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/** 888c2ecf20Sopenharmony_ci * jmicron_set_dma_mode - set host controller for DMA mode 898c2ecf20Sopenharmony_ci * @hwif: port 908c2ecf20Sopenharmony_ci * @drive: drive 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * As the JMicron snoops for timings we don't need to do anything here. 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic void jmicron_set_dma_mode(ide_hwif_t *hwif, ide_drive_t *drive) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic const struct ide_port_ops jmicron_port_ops = { 1008c2ecf20Sopenharmony_ci .set_pio_mode = jmicron_set_pio_mode, 1018c2ecf20Sopenharmony_ci .set_dma_mode = jmicron_set_dma_mode, 1028c2ecf20Sopenharmony_ci .cable_detect = jmicron_cable_detect, 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic const struct ide_port_info jmicron_chipset = { 1068c2ecf20Sopenharmony_ci .name = DRV_NAME, 1078c2ecf20Sopenharmony_ci .enablebits = { { 0x40, 0x01, 0x01 }, { 0x40, 0x10, 0x10 } }, 1088c2ecf20Sopenharmony_ci .port_ops = &jmicron_port_ops, 1098c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO5, 1108c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 1118c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA6, 1128c2ecf20Sopenharmony_ci}; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/** 1158c2ecf20Sopenharmony_ci * jmicron_init_one - pci layer discovery entry 1168c2ecf20Sopenharmony_ci * @dev: PCI device 1178c2ecf20Sopenharmony_ci * @id: ident table entry 1188c2ecf20Sopenharmony_ci * 1198c2ecf20Sopenharmony_ci * Called by the PCI code when it finds a Jmicron controller. 1208c2ecf20Sopenharmony_ci * We then use the IDE PCI generic helper to do most of the work. 1218c2ecf20Sopenharmony_ci */ 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic int jmicron_init_one(struct pci_dev *dev, const struct pci_device_id *id) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return ide_pci_init_one(dev, &jmicron_chipset, NULL); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci/* All JMB PATA controllers have and will continue to have the same 1298c2ecf20Sopenharmony_ci * interface. Matching vendor and device class is enough for all 1308c2ecf20Sopenharmony_ci * current and future controllers if the controller is programmed 1318c2ecf20Sopenharmony_ci * properly. 1328c2ecf20Sopenharmony_ci * 1338c2ecf20Sopenharmony_ci * If libata is configured, jmicron PCI quirk programs the controller 1348c2ecf20Sopenharmony_ci * into the correct mode. If libata isn't configured, match known 1358c2ecf20Sopenharmony_ci * device IDs too to maintain backward compatibility. 1368c2ecf20Sopenharmony_ci */ 1378c2ecf20Sopenharmony_cistatic struct pci_device_id jmicron_pci_tbl[] = { 1388c2ecf20Sopenharmony_ci#if !defined(CONFIG_ATA) && !defined(CONFIG_ATA_MODULE) 1398c2ecf20Sopenharmony_ci { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB361) }, 1408c2ecf20Sopenharmony_ci { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB363) }, 1418c2ecf20Sopenharmony_ci { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB365) }, 1428c2ecf20Sopenharmony_ci { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB366) }, 1438c2ecf20Sopenharmony_ci { PCI_VDEVICE(JMICRON, PCI_DEVICE_ID_JMICRON_JMB368) }, 1448c2ecf20Sopenharmony_ci#endif 1458c2ecf20Sopenharmony_ci { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 1468c2ecf20Sopenharmony_ci PCI_CLASS_STORAGE_IDE << 8, 0xffff00, 0 }, 1478c2ecf20Sopenharmony_ci { 0, }, 1488c2ecf20Sopenharmony_ci}; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, jmicron_pci_tbl); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_cistatic struct pci_driver jmicron_pci_driver = { 1538c2ecf20Sopenharmony_ci .name = "JMicron IDE", 1548c2ecf20Sopenharmony_ci .id_table = jmicron_pci_tbl, 1558c2ecf20Sopenharmony_ci .probe = jmicron_init_one, 1568c2ecf20Sopenharmony_ci .remove = ide_pci_remove, 1578c2ecf20Sopenharmony_ci .suspend = ide_pci_suspend, 1588c2ecf20Sopenharmony_ci .resume = ide_pci_resume, 1598c2ecf20Sopenharmony_ci}; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int __init jmicron_ide_init(void) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci return ide_pci_register_driver(&jmicron_pci_driver); 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic void __exit jmicron_ide_exit(void) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci pci_unregister_driver(&jmicron_pci_driver); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cimodule_init(jmicron_ide_init); 1728c2ecf20Sopenharmony_cimodule_exit(jmicron_ide_exit); 1738c2ecf20Sopenharmony_ci 1748c2ecf20Sopenharmony_ciMODULE_AUTHOR("Alan Cox"); 1758c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("PCI driver module for the JMicron in legacy modes"); 1768c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 177