Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * pata_triflex.c   - Compaq PATA for new ATA layer
0004  *            (C) 2005 Red Hat Inc
0005  *            Alan Cox <alan@lxorguk.ukuu.org.uk>
0006  *
0007  * based upon
0008  *
0009  * triflex.c
0010  *
0011  * IDE Chipset driver for the Compaq TriFlex IDE controller.
0012  *
0013  * Known to work with the Compaq Workstation 5x00 series.
0014  *
0015  * Copyright (C) 2002 Hewlett-Packard Development Group, L.P.
0016  * Author: Torben Mathiasen <torben.mathiasen@hp.com>
0017  *
0018  * Loosely based on the piix & svwks drivers.
0019  *
0020  * Documentation:
0021  *  Not publicly available.
0022  */
0023 
0024 #include <linux/kernel.h>
0025 #include <linux/module.h>
0026 #include <linux/pci.h>
0027 #include <linux/blkdev.h>
0028 #include <linux/delay.h>
0029 #include <scsi/scsi_host.h>
0030 #include <linux/libata.h>
0031 
0032 #define DRV_NAME "pata_triflex"
0033 #define DRV_VERSION "0.2.8"
0034 
0035 /**
0036  *  triflex_prereset        -   probe begin
0037  *  @link: ATA link
0038  *  @deadline: deadline jiffies for the operation
0039  *
0040  *  Set up cable type and use generic probe init
0041  */
0042 
0043 static int triflex_prereset(struct ata_link *link, unsigned long deadline)
0044 {
0045     static const struct pci_bits triflex_enable_bits[] = {
0046         { 0x80, 1, 0x01, 0x01 },
0047         { 0x80, 1, 0x02, 0x02 }
0048     };
0049 
0050     struct ata_port *ap = link->ap;
0051     struct pci_dev *pdev = to_pci_dev(ap->host->dev);
0052 
0053     if (!pci_test_config_bits(pdev, &triflex_enable_bits[ap->port_no]))
0054         return -ENOENT;
0055 
0056     return ata_sff_prereset(link, deadline);
0057 }
0058 
0059 
0060 
0061 /**
0062  *  triflex_load_timing     -   timing configuration
0063  *  @ap: ATA interface
0064  *  @adev: Device on the bus
0065  *  @speed: speed to configure
0066  *
0067  *  The Triflex has one set of timings per device per channel. This
0068  *  means we must do some switching. As the PIO and DMA timings don't
0069  *  match we have to do some reloading unlike PIIX devices where tuning
0070  *  tricks can avoid it.
0071  */
0072 
0073 static void triflex_load_timing(struct ata_port *ap, struct ata_device *adev, int speed)
0074 {
0075     struct pci_dev *pdev = to_pci_dev(ap->host->dev);
0076     u32 timing = 0;
0077     u32 triflex_timing, old_triflex_timing;
0078     int channel_offset = ap->port_no ? 0x74: 0x70;
0079     unsigned int is_slave   = (adev->devno != 0);
0080 
0081 
0082     pci_read_config_dword(pdev, channel_offset, &old_triflex_timing);
0083     triflex_timing = old_triflex_timing;
0084 
0085     switch(speed)
0086     {
0087         case XFER_MW_DMA_2:
0088             timing = 0x0103;break;
0089         case XFER_MW_DMA_1:
0090             timing = 0x0203;break;
0091         case XFER_MW_DMA_0:
0092             timing = 0x0808;break;
0093         case XFER_SW_DMA_2:
0094         case XFER_SW_DMA_1:
0095         case XFER_SW_DMA_0:
0096             timing = 0x0F0F;break;
0097         case XFER_PIO_4:
0098             timing = 0x0202;break;
0099         case XFER_PIO_3:
0100             timing = 0x0204;break;
0101         case XFER_PIO_2:
0102             timing = 0x0404;break;
0103         case XFER_PIO_1:
0104             timing = 0x0508;break;
0105         case XFER_PIO_0:
0106             timing = 0x0808;break;
0107         default:
0108             BUG();
0109     }
0110     triflex_timing &= ~ (0xFFFF << (16 * is_slave));
0111     triflex_timing |= (timing << (16 * is_slave));
0112 
0113     if (triflex_timing != old_triflex_timing)
0114         pci_write_config_dword(pdev, channel_offset, triflex_timing);
0115 }
0116 
0117 /**
0118  *  triflex_set_piomode -   set initial PIO mode data
0119  *  @ap: ATA interface
0120  *  @adev: ATA device
0121  *
0122  *  Use the timing loader to set up the PIO mode. We have to do this
0123  *  because DMA start/stop will only be called once DMA occurs. If there
0124  *  has been no DMA then the PIO timings are still needed.
0125  */
0126 static void triflex_set_piomode(struct ata_port *ap, struct ata_device *adev)
0127 {
0128     triflex_load_timing(ap, adev, adev->pio_mode);
0129 }
0130 
0131 /**
0132  *  triflex_bmdma_start -   DMA start callback
0133  *  @qc: Command in progress
0134  *
0135  *  Usually drivers set the DMA timing at the point the set_dmamode call
0136  *  is made. Triflex however requires we load new timings on the
0137  *  transition or keep matching PIO/DMA pairs (ie MWDMA2/PIO4 etc).
0138  *  We load the DMA timings just before starting DMA and then restore
0139  *  the PIO timing when the DMA is finished.
0140  */
0141 
0142 static void triflex_bmdma_start(struct ata_queued_cmd *qc)
0143 {
0144     triflex_load_timing(qc->ap, qc->dev, qc->dev->dma_mode);
0145     ata_bmdma_start(qc);
0146 }
0147 
0148 /**
0149  *  triflex_bmdma_stop  -   DMA stop callback
0150  *  @qc: ATA command
0151  *
0152  *  We loaded new timings in dma_start, as a result we need to restore
0153  *  the PIO timings in dma_stop so that the next command issue gets the
0154  *  right clock values.
0155  */
0156 
0157 static void triflex_bmdma_stop(struct ata_queued_cmd *qc)
0158 {
0159     ata_bmdma_stop(qc);
0160     triflex_load_timing(qc->ap, qc->dev, qc->dev->pio_mode);
0161 }
0162 
0163 static struct scsi_host_template triflex_sht = {
0164     ATA_BMDMA_SHT(DRV_NAME),
0165 };
0166 
0167 static struct ata_port_operations triflex_port_ops = {
0168     .inherits   = &ata_bmdma_port_ops,
0169     .bmdma_start    = triflex_bmdma_start,
0170     .bmdma_stop = triflex_bmdma_stop,
0171     .cable_detect   = ata_cable_40wire,
0172     .set_piomode    = triflex_set_piomode,
0173     .prereset   = triflex_prereset,
0174 };
0175 
0176 static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id)
0177 {
0178     static const struct ata_port_info info = {
0179         .flags = ATA_FLAG_SLAVE_POSS,
0180         .pio_mask = ATA_PIO4,
0181         .mwdma_mask = ATA_MWDMA2,
0182         .port_ops = &triflex_port_ops
0183     };
0184     const struct ata_port_info *ppi[] = { &info, NULL };
0185 
0186     ata_print_version_once(&dev->dev, DRV_VERSION);
0187 
0188     return ata_pci_bmdma_init_one(dev, ppi, &triflex_sht, NULL, 0);
0189 }
0190 
0191 static const struct pci_device_id triflex[] = {
0192     { PCI_VDEVICE(COMPAQ, PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE), },
0193 
0194     { },
0195 };
0196 
0197 #ifdef CONFIG_PM_SLEEP
0198 static int triflex_ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg)
0199 {
0200     struct ata_host *host = pci_get_drvdata(pdev);
0201 
0202     ata_host_suspend(host, mesg);
0203 
0204     /*
0205      * We must not disable or powerdown the device.
0206      * APM bios refuses to suspend if IDE is not accessible.
0207      */
0208     pci_save_state(pdev);
0209 
0210     return 0;
0211 }
0212 
0213 #endif
0214 
0215 static struct pci_driver triflex_pci_driver = {
0216     .name       = DRV_NAME,
0217     .id_table   = triflex,
0218     .probe      = triflex_init_one,
0219     .remove     = ata_pci_remove_one,
0220 #ifdef CONFIG_PM_SLEEP
0221     .suspend    = triflex_ata_pci_device_suspend,
0222     .resume     = ata_pci_device_resume,
0223 #endif
0224 };
0225 
0226 module_pci_driver(triflex_pci_driver);
0227 
0228 MODULE_AUTHOR("Alan Cox");
0229 MODULE_DESCRIPTION("low-level driver for Compaq Triflex");
0230 MODULE_LICENSE("GPL");
0231 MODULE_DEVICE_TABLE(pci, triflex);
0232 MODULE_VERSION(DRV_VERSION);