162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * New ATA layer SC1200 driver Alan Cox <alan@lxorguk.ukuu.org.uk> 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * TODO: Mode selection filtering 662306a36Sopenharmony_ci * TODO: Needs custom DMA cleanup code 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * Based very heavily on 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> 1362306a36Sopenharmony_ci * May be copied or modified under the terms of the GNU General Public License 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Development of this chipset driver was funded 1662306a36Sopenharmony_ci * by the nice folks at National Semiconductor. 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/kernel.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/pci.h> 2262306a36Sopenharmony_ci#include <linux/blkdev.h> 2362306a36Sopenharmony_ci#include <linux/delay.h> 2462306a36Sopenharmony_ci#include <scsi/scsi_host.h> 2562306a36Sopenharmony_ci#include <linux/libata.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#define DRV_NAME "pata_sc1200" 2862306a36Sopenharmony_ci#define DRV_VERSION "0.2.6" 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci#define SC1200_REV_A 0x00 3162306a36Sopenharmony_ci#define SC1200_REV_B1 0x01 3262306a36Sopenharmony_ci#define SC1200_REV_B3 0x02 3362306a36Sopenharmony_ci#define SC1200_REV_C1 0x03 3462306a36Sopenharmony_ci#define SC1200_REV_D1 0x04 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/** 3762306a36Sopenharmony_ci * sc1200_clock - PCI clock 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * Return the PCI bus clocking for the SC1200 chipset configuration 4062306a36Sopenharmony_ci * in use. We return 0 for 33MHz 1 for 48MHz and 2 for 66Mhz 4162306a36Sopenharmony_ci */ 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic int sc1200_clock(void) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci /* Magic registers that give us the chipset data */ 4662306a36Sopenharmony_ci u8 chip_id = inb(0x903C); 4762306a36Sopenharmony_ci u8 silicon_rev = inb(0x903D); 4862306a36Sopenharmony_ci u16 pci_clock; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (chip_id == 0x04 && silicon_rev < SC1200_REV_B1) 5162306a36Sopenharmony_ci return 0; /* 33 MHz mode */ 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* Clock generator configuration 0x901E its 8/9 are the PCI clocking 5462306a36Sopenharmony_ci 0/3 is 33Mhz 1 is 48 2 is 66 */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci pci_clock = inw(0x901E); 5762306a36Sopenharmony_ci pci_clock >>= 8; 5862306a36Sopenharmony_ci pci_clock &= 0x03; 5962306a36Sopenharmony_ci if (pci_clock == 3) 6062306a36Sopenharmony_ci pci_clock = 0; 6162306a36Sopenharmony_ci return pci_clock; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/** 6562306a36Sopenharmony_ci * sc1200_set_piomode - PIO setup 6662306a36Sopenharmony_ci * @ap: ATA interface 6762306a36Sopenharmony_ci * @adev: device on the interface 6862306a36Sopenharmony_ci * 6962306a36Sopenharmony_ci * Set our PIO requirements. This is fairly simple on the SC1200 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_cistatic void sc1200_set_piomode(struct ata_port *ap, struct ata_device *adev) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci static const u32 pio_timings[4][5] = { 7562306a36Sopenharmony_ci /* format0, 33Mhz */ 7662306a36Sopenharmony_ci { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 }, 7762306a36Sopenharmony_ci /* format1, 33Mhz */ 7862306a36Sopenharmony_ci { 0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010 }, 7962306a36Sopenharmony_ci /* format1, 48Mhz */ 8062306a36Sopenharmony_ci { 0xfaa3f4f3, 0xc23232b2, 0x513101c1, 0x31213121, 0x10211021 }, 8162306a36Sopenharmony_ci /* format1, 66Mhz */ 8262306a36Sopenharmony_ci { 0xfff4fff4, 0xf35353d3, 0x814102f1, 0x42314231, 0x11311131 } 8362306a36Sopenharmony_ci }; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(ap->host->dev); 8662306a36Sopenharmony_ci u32 format; 8762306a36Sopenharmony_ci unsigned int reg = 0x40 + 0x10 * ap->port_no; 8862306a36Sopenharmony_ci int mode = adev->pio_mode - XFER_PIO_0; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci pci_read_config_dword(pdev, reg + 4, &format); 9162306a36Sopenharmony_ci format >>= 31; 9262306a36Sopenharmony_ci format += sc1200_clock(); 9362306a36Sopenharmony_ci pci_write_config_dword(pdev, reg + 8 * adev->devno, 9462306a36Sopenharmony_ci pio_timings[format][mode]); 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/** 9862306a36Sopenharmony_ci * sc1200_set_dmamode - DMA timing setup 9962306a36Sopenharmony_ci * @ap: ATA interface 10062306a36Sopenharmony_ci * @adev: Device being configured 10162306a36Sopenharmony_ci * 10262306a36Sopenharmony_ci * We cannot mix MWDMA and UDMA without reloading timings each switch 10362306a36Sopenharmony_ci * master to slave. 10462306a36Sopenharmony_ci */ 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic void sc1200_set_dmamode(struct ata_port *ap, struct ata_device *adev) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci static const u32 udma_timing[3][3] = { 10962306a36Sopenharmony_ci { 0x00921250, 0x00911140, 0x00911030 }, 11062306a36Sopenharmony_ci { 0x00932470, 0x00922260, 0x00922140 }, 11162306a36Sopenharmony_ci { 0x009436A1, 0x00933481, 0x00923261 } 11262306a36Sopenharmony_ci }; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci static const u32 mwdma_timing[3][3] = { 11562306a36Sopenharmony_ci { 0x00077771, 0x00012121, 0x00002020 }, 11662306a36Sopenharmony_ci { 0x000BBBB2, 0x00024241, 0x00013131 }, 11762306a36Sopenharmony_ci { 0x000FFFF3, 0x00035352, 0x00015151 } 11862306a36Sopenharmony_ci }; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci int clock = sc1200_clock(); 12162306a36Sopenharmony_ci struct pci_dev *pdev = to_pci_dev(ap->host->dev); 12262306a36Sopenharmony_ci unsigned int reg = 0x40 + 0x10 * ap->port_no; 12362306a36Sopenharmony_ci int mode = adev->dma_mode; 12462306a36Sopenharmony_ci u32 format; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci if (mode >= XFER_UDMA_0) 12762306a36Sopenharmony_ci format = udma_timing[clock][mode - XFER_UDMA_0]; 12862306a36Sopenharmony_ci else 12962306a36Sopenharmony_ci format = mwdma_timing[clock][mode - XFER_MW_DMA_0]; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci if (adev->devno == 0) { 13262306a36Sopenharmony_ci u32 timings; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci pci_read_config_dword(pdev, reg + 4, &timings); 13562306a36Sopenharmony_ci timings &= 0x80000000UL; 13662306a36Sopenharmony_ci timings |= format; 13762306a36Sopenharmony_ci pci_write_config_dword(pdev, reg + 4, timings); 13862306a36Sopenharmony_ci } else 13962306a36Sopenharmony_ci pci_write_config_dword(pdev, reg + 12, format); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci/** 14362306a36Sopenharmony_ci * sc1200_qc_issue - command issue 14462306a36Sopenharmony_ci * @qc: command pending 14562306a36Sopenharmony_ci * 14662306a36Sopenharmony_ci * Called when the libata layer is about to issue a command. We wrap 14762306a36Sopenharmony_ci * this interface so that we can load the correct ATA timings if 14862306a36Sopenharmony_ci * necessary. Specifically we have a problem that there is only 14962306a36Sopenharmony_ci * one MWDMA/UDMA bit. 15062306a36Sopenharmony_ci */ 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci struct ata_port *ap = qc->ap; 15562306a36Sopenharmony_ci struct ata_device *adev = qc->dev; 15662306a36Sopenharmony_ci struct ata_device *prev = ap->private_data; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci /* See if the DMA settings could be wrong */ 15962306a36Sopenharmony_ci if (ata_dma_enabled(adev) && adev != prev && prev != NULL) { 16062306a36Sopenharmony_ci /* Maybe, but do the channels match MWDMA/UDMA ? */ 16162306a36Sopenharmony_ci if ((ata_using_udma(adev) && !ata_using_udma(prev)) || 16262306a36Sopenharmony_ci (ata_using_udma(prev) && !ata_using_udma(adev))) 16362306a36Sopenharmony_ci /* Switch the mode bits */ 16462306a36Sopenharmony_ci sc1200_set_dmamode(ap, adev); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci return ata_bmdma_qc_issue(qc); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci/** 17162306a36Sopenharmony_ci * sc1200_qc_defer - implement serialization 17262306a36Sopenharmony_ci * @qc: command 17362306a36Sopenharmony_ci * 17462306a36Sopenharmony_ci * Serialize command issue on this controller. 17562306a36Sopenharmony_ci */ 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic int sc1200_qc_defer(struct ata_queued_cmd *qc) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci struct ata_host *host = qc->ap->host; 18062306a36Sopenharmony_ci struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; 18162306a36Sopenharmony_ci int rc; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci /* First apply the usual rules */ 18462306a36Sopenharmony_ci rc = ata_std_qc_defer(qc); 18562306a36Sopenharmony_ci if (rc != 0) 18662306a36Sopenharmony_ci return rc; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci /* Now apply serialization rules. Only allow a command if the 18962306a36Sopenharmony_ci other channel state machine is idle */ 19062306a36Sopenharmony_ci if (alt && alt->qc_active) 19162306a36Sopenharmony_ci return ATA_DEFER_PORT; 19262306a36Sopenharmony_ci return 0; 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistatic const struct scsi_host_template sc1200_sht = { 19662306a36Sopenharmony_ci ATA_BASE_SHT(DRV_NAME), 19762306a36Sopenharmony_ci .sg_tablesize = LIBATA_DUMB_MAX_PRD, 19862306a36Sopenharmony_ci .dma_boundary = ATA_DMA_BOUNDARY, 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic struct ata_port_operations sc1200_port_ops = { 20262306a36Sopenharmony_ci .inherits = &ata_bmdma_port_ops, 20362306a36Sopenharmony_ci .qc_prep = ata_bmdma_dumb_qc_prep, 20462306a36Sopenharmony_ci .qc_issue = sc1200_qc_issue, 20562306a36Sopenharmony_ci .qc_defer = sc1200_qc_defer, 20662306a36Sopenharmony_ci .cable_detect = ata_cable_40wire, 20762306a36Sopenharmony_ci .set_piomode = sc1200_set_piomode, 20862306a36Sopenharmony_ci .set_dmamode = sc1200_set_dmamode, 20962306a36Sopenharmony_ci}; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci/** 21262306a36Sopenharmony_ci * sc1200_init_one - Initialise an SC1200 21362306a36Sopenharmony_ci * @dev: PCI device 21462306a36Sopenharmony_ci * @id: Entry in match table 21562306a36Sopenharmony_ci * 21662306a36Sopenharmony_ci * Just throw the needed data at the libata helper and it does all 21762306a36Sopenharmony_ci * our work. 21862306a36Sopenharmony_ci */ 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci static const struct ata_port_info info = { 22362306a36Sopenharmony_ci .flags = ATA_FLAG_SLAVE_POSS, 22462306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 22562306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 22662306a36Sopenharmony_ci .udma_mask = ATA_UDMA2, 22762306a36Sopenharmony_ci .port_ops = &sc1200_port_ops 22862306a36Sopenharmony_ci }; 22962306a36Sopenharmony_ci const struct ata_port_info *ppi[] = { &info, NULL }; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci return ata_pci_bmdma_init_one(dev, ppi, &sc1200_sht, NULL, 0); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic const struct pci_device_id sc1200[] = { 23562306a36Sopenharmony_ci { PCI_VDEVICE(NS, PCI_DEVICE_ID_NS_SCx200_IDE), }, 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci { }, 23862306a36Sopenharmony_ci}; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_cistatic struct pci_driver sc1200_pci_driver = { 24162306a36Sopenharmony_ci .name = DRV_NAME, 24262306a36Sopenharmony_ci .id_table = sc1200, 24362306a36Sopenharmony_ci .probe = sc1200_init_one, 24462306a36Sopenharmony_ci .remove = ata_pci_remove_one, 24562306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 24662306a36Sopenharmony_ci .suspend = ata_pci_device_suspend, 24762306a36Sopenharmony_ci .resume = ata_pci_device_resume, 24862306a36Sopenharmony_ci#endif 24962306a36Sopenharmony_ci}; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cimodule_pci_driver(sc1200_pci_driver); 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ciMODULE_AUTHOR("Alan Cox, Mark Lord"); 25462306a36Sopenharmony_ciMODULE_DESCRIPTION("low-level driver for the NS/AMD SC1200"); 25562306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 25662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, sc1200); 25762306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 258