linux/drivers/ata/pata_sch.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  pata_sch.c - Intel SCH PATA controllers
   4 *
   5 *  Copyright (c) 2008 Alek Du <alek.du@intel.com>
   6 */
   7
   8/*
   9 *  Supports:
  10 *    Intel SCH (AF82US15W, AF82US15L, AF82UL11L) chipsets -- see spec at:
  11 *    http://download.intel.com/design/chipsets/embedded/datashts/319537.pdf
  12 */
  13
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/pci.h>
  17#include <linux/blkdev.h>
  18#include <linux/delay.h>
  19#include <linux/device.h>
  20#include <scsi/scsi_host.h>
  21#include <linux/libata.h>
  22#include <linux/dmi.h>
  23
  24#define DRV_NAME        "pata_sch"
  25#define DRV_VERSION     "0.2"
  26
  27/* see SCH datasheet page 351 */
  28enum {
  29        D0TIM   = 0x80,         /* Device 0 Timing Register */
  30        D1TIM   = 0x84,         /* Device 1 Timing Register */
  31        PM      = 0x07,         /* PIO Mode Bit Mask */
  32        MDM     = (0x03 << 8),  /* Multi-word DMA Mode Bit Mask */
  33        UDM     = (0x07 << 16), /* Ultra DMA Mode Bit Mask */
  34        PPE     = (1 << 30),    /* Prefetch/Post Enable */
  35        USD     = (1 << 31),    /* Use Synchronous DMA */
  36};
  37
  38static int sch_init_one(struct pci_dev *pdev,
  39                         const struct pci_device_id *ent);
  40static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev);
  41static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev);
  42
  43static const struct pci_device_id sch_pci_tbl[] = {
  44        /* Intel SCH PATA Controller */
  45        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_SCH_IDE), 0 },
  46        { }     /* terminate list */
  47};
  48
  49static struct pci_driver sch_pci_driver = {
  50        .name                   = DRV_NAME,
  51        .id_table               = sch_pci_tbl,
  52        .probe                  = sch_init_one,
  53        .remove                 = ata_pci_remove_one,
  54#ifdef CONFIG_PM_SLEEP
  55        .suspend                = ata_pci_device_suspend,
  56        .resume                 = ata_pci_device_resume,
  57#endif
  58};
  59
  60static struct scsi_host_template sch_sht = {
  61        ATA_BMDMA_SHT(DRV_NAME),
  62};
  63
  64static struct ata_port_operations sch_pata_ops = {
  65        .inherits               = &ata_bmdma_port_ops,
  66        .cable_detect           = ata_cable_unknown,
  67        .set_piomode            = sch_set_piomode,
  68        .set_dmamode            = sch_set_dmamode,
  69};
  70
  71static const struct ata_port_info sch_port_info = {
  72        .flags          = ATA_FLAG_SLAVE_POSS,
  73        .pio_mask       = ATA_PIO4,
  74        .mwdma_mask     = ATA_MWDMA2,
  75        .udma_mask      = ATA_UDMA5,
  76        .port_ops       = &sch_pata_ops,
  77};
  78
  79MODULE_AUTHOR("Alek Du <alek.du@intel.com>");
  80MODULE_DESCRIPTION("SCSI low-level driver for Intel SCH PATA controllers");
  81MODULE_LICENSE("GPL");
  82MODULE_DEVICE_TABLE(pci, sch_pci_tbl);
  83MODULE_VERSION(DRV_VERSION);
  84
  85/**
  86 *      sch_set_piomode - Initialize host controller PATA PIO timings
  87 *      @ap: Port whose timings we are configuring
  88 *      @adev: ATA device
  89 *
  90 *      Set PIO mode for device, in host controller PCI config space.
  91 *
  92 *      LOCKING:
  93 *      None (inherited from caller).
  94 */
  95
  96static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev)
  97{
  98        unsigned int pio        = adev->pio_mode - XFER_PIO_0;
  99        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
 100        unsigned int port       = adev->devno ? D1TIM : D0TIM;
 101        unsigned int data;
 102
 103        pci_read_config_dword(dev, port, &data);
 104        /* see SCH datasheet page 351 */
 105        /* set PIO mode */
 106        data &= ~(PM | PPE);
 107        data |= pio;
 108        /* enable PPE for block device */
 109        if (adev->class == ATA_DEV_ATA)
 110                data |= PPE;
 111        pci_write_config_dword(dev, port, data);
 112}
 113
 114/**
 115 *      sch_set_dmamode - Initialize host controller PATA DMA timings
 116 *      @ap: Port whose timings we are configuring
 117 *      @adev: ATA device
 118 *
 119 *      Set MW/UDMA mode for device, in host controller PCI config space.
 120 *
 121 *      LOCKING:
 122 *      None (inherited from caller).
 123 */
 124
 125static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev)
 126{
 127        unsigned int dma_mode   = adev->dma_mode;
 128        struct pci_dev *dev     = to_pci_dev(ap->host->dev);
 129        unsigned int port       = adev->devno ? D1TIM : D0TIM;
 130        unsigned int data;
 131
 132        pci_read_config_dword(dev, port, &data);
 133        /* see SCH datasheet page 351 */
 134        if (dma_mode >= XFER_UDMA_0) {
 135                /* enable Synchronous DMA mode */
 136                data |= USD;
 137                data &= ~UDM;
 138                data |= (dma_mode - XFER_UDMA_0) << 16;
 139        } else { /* must be MWDMA mode, since we masked SWDMA already */
 140                data &= ~(USD | MDM);
 141                data |= (dma_mode - XFER_MW_DMA_0) << 8;
 142        }
 143        pci_write_config_dword(dev, port, data);
 144}
 145
 146/**
 147 *      sch_init_one - Register SCH ATA PCI device with kernel services
 148 *      @pdev: PCI device to register
 149 *      @ent: Entry in sch_pci_tbl matching with @pdev
 150 *
 151 *      LOCKING:
 152 *      Inherited from PCI layer (may sleep).
 153 *
 154 *      RETURNS:
 155 *      Zero on success, or -ERRNO value.
 156 */
 157
 158static int sch_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 159{
 160        const struct ata_port_info *ppi[] = { &sch_port_info, NULL };
 161
 162        ata_print_version_once(&pdev->dev, DRV_VERSION);
 163
 164        return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
 165}
 166
 167module_pci_driver(sch_pci_driver);
 168