Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * pata-cs5530.c    - CS5530 PATA for new ATA layer
0004  *            (C) 2005 Red Hat Inc
0005  *
0006  * based upon cs5530.c by Mark Lord.
0007  *
0008  * Loosely based on the piix & svwks drivers.
0009  *
0010  * Documentation:
0011  *  Available from AMD web site.
0012  */
0013 
0014 #include <linux/kernel.h>
0015 #include <linux/module.h>
0016 #include <linux/pci.h>
0017 #include <linux/blkdev.h>
0018 #include <linux/delay.h>
0019 #include <scsi/scsi_host.h>
0020 #include <linux/libata.h>
0021 #include <linux/dmi.h>
0022 
0023 #define DRV_NAME    "pata_cs5530"
0024 #define DRV_VERSION "0.7.4"
0025 
0026 static void __iomem *cs5530_port_base(struct ata_port *ap)
0027 {
0028     unsigned long bmdma = (unsigned long)ap->ioaddr.bmdma_addr;
0029 
0030     return (void __iomem *)((bmdma & ~0x0F) + 0x20 + 0x10 * ap->port_no);
0031 }
0032 
0033 /**
0034  *  cs5530_set_piomode      -   PIO setup
0035  *  @ap: ATA interface
0036  *  @adev: device on the interface
0037  *
0038  *  Set our PIO requirements. This is fairly simple on the CS5530
0039  *  chips.
0040  */
0041 
0042 static void cs5530_set_piomode(struct ata_port *ap, struct ata_device *adev)
0043 {
0044     static const unsigned int cs5530_pio_timings[2][5] = {
0045         {0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010},
0046         {0xd1329172, 0x71212171, 0x30200080, 0x20102010, 0x00100010}
0047     };
0048     void __iomem *base = cs5530_port_base(ap);
0049     u32 tuning;
0050     int format;
0051 
0052     /* Find out which table to use */
0053     tuning = ioread32(base + 0x04);
0054     format = (tuning & 0x80000000UL) ? 1 : 0;
0055 
0056     /* Now load the right timing register */
0057     if (adev->devno)
0058         base += 0x08;
0059 
0060     iowrite32(cs5530_pio_timings[format][adev->pio_mode - XFER_PIO_0], base);
0061 }
0062 
0063 /**
0064  *  cs5530_set_dmamode      -   DMA timing setup
0065  *  @ap: ATA interface
0066  *  @adev: Device being configured
0067  *
0068  *  We cannot mix MWDMA and UDMA without reloading timings each switch
0069  *  master to slave. We track the last DMA setup in order to minimise
0070  *  reloads.
0071  */
0072 
0073 static void cs5530_set_dmamode(struct ata_port *ap, struct ata_device *adev)
0074 {
0075     void __iomem *base = cs5530_port_base(ap);
0076     u32 tuning, timing = 0;
0077     u8 reg;
0078 
0079     /* Find out which table to use */
0080     tuning = ioread32(base + 0x04);
0081 
0082     switch(adev->dma_mode) {
0083         case XFER_UDMA_0:
0084             timing  = 0x00921250;break;
0085         case XFER_UDMA_1:
0086             timing  = 0x00911140;break;
0087         case XFER_UDMA_2:
0088             timing  = 0x00911030;break;
0089         case XFER_MW_DMA_0:
0090             timing  = 0x00077771;break;
0091         case XFER_MW_DMA_1:
0092             timing  = 0x00012121;break;
0093         case XFER_MW_DMA_2:
0094             timing  = 0x00002020;break;
0095         default:
0096             BUG();
0097     }
0098     /* Merge in the PIO format bit */
0099     timing |= (tuning & 0x80000000UL);
0100     if (adev->devno == 0) /* Master */
0101         iowrite32(timing, base + 0x04);
0102     else {
0103         if (timing & 0x00100000)
0104             tuning |= 0x00100000;   /* UDMA for both */
0105         else
0106             tuning &= ~0x00100000;  /* MWDMA for both */
0107         iowrite32(tuning, base + 0x04);
0108         iowrite32(timing, base + 0x0C);
0109     }
0110 
0111     /* Set the DMA capable bit in the BMDMA area */
0112     reg = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
0113     reg |= (1 << (5 + adev->devno));
0114     iowrite8(reg, ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
0115 
0116     /* Remember the last DMA setup we did */
0117 
0118     ap->private_data = adev;
0119 }
0120 
0121 /**
0122  *  cs5530_qc_issue     -   command issue
0123  *  @qc: command pending
0124  *
0125  *  Called when the libata layer is about to issue a command. We wrap
0126  *  this interface so that we can load the correct ATA timings if
0127  *  necessary.  Specifically we have a problem that there is only
0128  *  one MWDMA/UDMA bit.
0129  */
0130 
0131 static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc)
0132 {
0133     struct ata_port *ap = qc->ap;
0134     struct ata_device *adev = qc->dev;
0135     struct ata_device *prev = ap->private_data;
0136 
0137     /* See if the DMA settings could be wrong */
0138     if (ata_dma_enabled(adev) && adev != prev && prev != NULL) {
0139         /* Maybe, but do the channels match MWDMA/UDMA ? */
0140         if ((ata_using_udma(adev) && !ata_using_udma(prev)) ||
0141             (ata_using_udma(prev) && !ata_using_udma(adev)))
0142                 /* Switch the mode bits */
0143                 cs5530_set_dmamode(ap, adev);
0144     }
0145 
0146     return ata_bmdma_qc_issue(qc);
0147 }
0148 
0149 static struct scsi_host_template cs5530_sht = {
0150     ATA_BASE_SHT(DRV_NAME),
0151     .sg_tablesize   = LIBATA_DUMB_MAX_PRD,
0152     .dma_boundary   = ATA_DMA_BOUNDARY,
0153 };
0154 
0155 static struct ata_port_operations cs5530_port_ops = {
0156     .inherits   = &ata_bmdma_port_ops,
0157 
0158     .qc_prep    = ata_bmdma_dumb_qc_prep,
0159     .qc_issue   = cs5530_qc_issue,
0160 
0161     .cable_detect   = ata_cable_40wire,
0162     .set_piomode    = cs5530_set_piomode,
0163     .set_dmamode    = cs5530_set_dmamode,
0164 };
0165 
0166 static const struct dmi_system_id palmax_dmi_table[] = {
0167     {
0168         .ident = "Palmax PD1100",
0169         .matches = {
0170             DMI_MATCH(DMI_SYS_VENDOR, "Cyrix"),
0171             DMI_MATCH(DMI_PRODUCT_NAME, "Caddis"),
0172         },
0173     },
0174     { }
0175 };
0176 
0177 static int cs5530_is_palmax(void)
0178 {
0179     if (dmi_check_system(palmax_dmi_table)) {
0180         printk(KERN_INFO "Palmax PD1100: Disabling DMA on docking port.\n");
0181         return 1;
0182     }
0183     return 0;
0184 }
0185 
0186 
0187 /**
0188  *  cs5530_init_chip    -   Chipset init
0189  *
0190  *  Perform the chip initialisation work that is shared between both
0191  *  setup and resume paths
0192  */
0193 
0194 static int cs5530_init_chip(void)
0195 {
0196     struct pci_dev *master_0 = NULL, *cs5530_0 = NULL, *dev = NULL;
0197 
0198     while ((dev = pci_get_device(PCI_VENDOR_ID_CYRIX, PCI_ANY_ID, dev)) != NULL) {
0199         switch (dev->device) {
0200             case PCI_DEVICE_ID_CYRIX_PCI_MASTER:
0201                 master_0 = pci_dev_get(dev);
0202                 break;
0203             case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
0204                 cs5530_0 = pci_dev_get(dev);
0205                 break;
0206         }
0207     }
0208     if (!master_0) {
0209         printk(KERN_ERR DRV_NAME ": unable to locate PCI MASTER function\n");
0210         goto fail_put;
0211     }
0212     if (!cs5530_0) {
0213         printk(KERN_ERR DRV_NAME ": unable to locate CS5530 LEGACY function\n");
0214         goto fail_put;
0215     }
0216 
0217     pci_set_master(cs5530_0);
0218     pci_try_set_mwi(cs5530_0);
0219 
0220     /*
0221      * Set PCI CacheLineSize to 16-bytes:
0222      * --> Write 0x04 into 8-bit PCI CACHELINESIZE reg of function 0 of the cs5530
0223      *
0224      * Note: This value is constant because the 5530 is only a Geode companion
0225      */
0226 
0227     pci_write_config_byte(cs5530_0, PCI_CACHE_LINE_SIZE, 0x04);
0228 
0229     /*
0230      * Disable trapping of UDMA register accesses (Win98 hack):
0231      * --> Write 0x5006 into 16-bit reg at offset 0xd0 of function 0 of the cs5530
0232      */
0233 
0234     pci_write_config_word(cs5530_0, 0xd0, 0x5006);
0235 
0236     /*
0237      * Bit-1 at 0x40 enables MemoryWriteAndInvalidate on internal X-bus:
0238      * The other settings are what is necessary to get the register
0239      * into a sane state for IDE DMA operation.
0240      */
0241 
0242     pci_write_config_byte(master_0, 0x40, 0x1e);
0243 
0244     /*
0245      * Set max PCI burst size (16-bytes seems to work best):
0246      *     16bytes: set bit-1 at 0x41 (reg value of 0x16)
0247      *  all others: clear bit-1 at 0x41, and do:
0248      *    128bytes: OR 0x00 at 0x41
0249      *    256bytes: OR 0x04 at 0x41
0250      *    512bytes: OR 0x08 at 0x41
0251      *   1024bytes: OR 0x0c at 0x41
0252      */
0253 
0254     pci_write_config_byte(master_0, 0x41, 0x14);
0255 
0256     /*
0257      * These settings are necessary to get the chip
0258      * into a sane state for IDE DMA operation.
0259      */
0260 
0261     pci_write_config_byte(master_0, 0x42, 0x00);
0262     pci_write_config_byte(master_0, 0x43, 0xc1);
0263 
0264     pci_dev_put(master_0);
0265     pci_dev_put(cs5530_0);
0266     return 0;
0267 fail_put:
0268     pci_dev_put(master_0);
0269     pci_dev_put(cs5530_0);
0270     return -ENODEV;
0271 }
0272 
0273 /**
0274  *  cs5530_init_one     -   Initialise a CS5530
0275  *  @pdev: PCI device
0276  *  @id: Entry in match table
0277  *
0278  *  Install a driver for the newly found CS5530 companion chip. Most of
0279  *  this is just housekeeping. We have to set the chip up correctly and
0280  *  turn off various bits of emulation magic.
0281  */
0282 
0283 static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
0284 {
0285     static const struct ata_port_info info = {
0286         .flags = ATA_FLAG_SLAVE_POSS,
0287         .pio_mask = ATA_PIO4,
0288         .mwdma_mask = ATA_MWDMA2,
0289         .udma_mask = ATA_UDMA2,
0290         .port_ops = &cs5530_port_ops
0291     };
0292     /* The docking connector doesn't do UDMA, and it seems not MWDMA */
0293     static const struct ata_port_info info_palmax_secondary = {
0294         .flags = ATA_FLAG_SLAVE_POSS,
0295         .pio_mask = ATA_PIO4,
0296         .port_ops = &cs5530_port_ops
0297     };
0298     const struct ata_port_info *ppi[] = { &info, NULL };
0299     int rc;
0300 
0301     rc = pcim_enable_device(pdev);
0302     if (rc)
0303         return rc;
0304 
0305     /* Chip initialisation */
0306     if (cs5530_init_chip())
0307         return -ENODEV;
0308 
0309     if (cs5530_is_palmax())
0310         ppi[1] = &info_palmax_secondary;
0311 
0312     /* Now kick off ATA set up */
0313     return ata_pci_bmdma_init_one(pdev, ppi, &cs5530_sht, NULL, 0);
0314 }
0315 
0316 #ifdef CONFIG_PM_SLEEP
0317 static int cs5530_reinit_one(struct pci_dev *pdev)
0318 {
0319     struct ata_host *host = pci_get_drvdata(pdev);
0320     int rc;
0321 
0322     rc = ata_pci_device_do_resume(pdev);
0323     if (rc)
0324         return rc;
0325 
0326     /* If we fail on resume we are doomed */
0327     if (cs5530_init_chip())
0328         return -EIO;
0329 
0330     ata_host_resume(host);
0331     return 0;
0332 }
0333 #endif /* CONFIG_PM_SLEEP */
0334 
0335 static const struct pci_device_id cs5530[] = {
0336     { PCI_VDEVICE(CYRIX, PCI_DEVICE_ID_CYRIX_5530_IDE), },
0337 
0338     { },
0339 };
0340 
0341 static struct pci_driver cs5530_pci_driver = {
0342     .name       = DRV_NAME,
0343     .id_table   = cs5530,
0344     .probe      = cs5530_init_one,
0345     .remove     = ata_pci_remove_one,
0346 #ifdef CONFIG_PM_SLEEP
0347     .suspend    = ata_pci_device_suspend,
0348     .resume     = cs5530_reinit_one,
0349 #endif
0350 };
0351 
0352 module_pci_driver(cs5530_pci_driver);
0353 
0354 MODULE_AUTHOR("Alan Cox");
0355 MODULE_DESCRIPTION("low-level driver for the Cyrix/NS/AMD 5530");
0356 MODULE_LICENSE("GPL");
0357 MODULE_DEVICE_TABLE(pci, cs5530);
0358 MODULE_VERSION(DRV_VERSION);