| 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 */ | 
|---|
| 28 | enum { | 
|---|
| 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 |  | 
|---|
| 38 | static int sch_init_one(struct pci_dev *pdev, | 
|---|
| 39 | const struct pci_device_id *ent); | 
|---|
| 40 | static void sch_set_piomode(struct ata_port *ap, struct ata_device *adev); | 
|---|
| 41 | static void sch_set_dmamode(struct ata_port *ap, struct ata_device *adev); | 
|---|
| 42 |  | 
|---|
| 43 | static 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 |  | 
|---|
| 49 | static 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 |  | 
|---|
| 60 | static const struct scsi_host_template sch_sht = { | 
|---|
| 61 | ATA_BMDMA_SHT(DRV_NAME), | 
|---|
| 62 | }; | 
|---|
| 63 |  | 
|---|
| 64 | static 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 |  | 
|---|
| 71 | static 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 |  | 
|---|
| 79 | MODULE_AUTHOR( "Alek Du <alek.du@intel.com>"); | 
|---|
| 80 | MODULE_DESCRIPTION( "SCSI low-level driver for Intel SCH PATA controllers"); | 
|---|
| 81 | MODULE_LICENSE( "GPL"); | 
|---|
| 82 | MODULE_DEVICE_TABLE(pci, sch_pci_tbl); | 
|---|
| 83 | MODULE_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 |  | 
|---|
| 96 | static 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, where: port, val: &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, where: port, val: 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 |  | 
|---|
| 125 | static 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, where: port, val: &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, where: port, val: 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 |  | 
|---|
| 158 | static 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(dev: &pdev->dev, DRV_VERSION); | 
|---|
| 163 |  | 
|---|
| 164 | return ata_pci_bmdma_init_one(pdev, ppi, sht: &sch_sht, NULL, hflags: 0); | 
|---|
| 165 | } | 
|---|
| 166 |  | 
|---|
| 167 | module_pci_driver(sch_pci_driver); | 
|---|
| 168 |  | 
|---|