xref: /OK3568_Linux_fs/kernel/drivers/ata/pata_acpi.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *	ACPI PATA driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  *	(c) 2007 Red Hat
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/kernel.h>
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/pci.h>
11*4882a593Smuzhiyun #include <linux/blkdev.h>
12*4882a593Smuzhiyun #include <linux/delay.h>
13*4882a593Smuzhiyun #include <linux/device.h>
14*4882a593Smuzhiyun #include <linux/gfp.h>
15*4882a593Smuzhiyun #include <linux/acpi.h>
16*4882a593Smuzhiyun #include <linux/libata.h>
17*4882a593Smuzhiyun #include <linux/ata.h>
18*4882a593Smuzhiyun #include <scsi/scsi_host.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #define DRV_NAME	"pata_acpi"
21*4882a593Smuzhiyun #define DRV_VERSION	"0.2.3"
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun struct pata_acpi {
24*4882a593Smuzhiyun 	struct ata_acpi_gtm gtm;
25*4882a593Smuzhiyun 	void *last;
26*4882a593Smuzhiyun 	unsigned long mask[2];
27*4882a593Smuzhiyun };
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun /**
30*4882a593Smuzhiyun  *	pacpi_pre_reset	-	check for 40/80 pin
31*4882a593Smuzhiyun  *	@ap: Port
32*4882a593Smuzhiyun  *	@deadline: deadline jiffies for the operation
33*4882a593Smuzhiyun  *
34*4882a593Smuzhiyun  *	Perform the PATA port setup we need.
35*4882a593Smuzhiyun  */
36*4882a593Smuzhiyun 
pacpi_pre_reset(struct ata_link * link,unsigned long deadline)37*4882a593Smuzhiyun static int pacpi_pre_reset(struct ata_link *link, unsigned long deadline)
38*4882a593Smuzhiyun {
39*4882a593Smuzhiyun 	struct ata_port *ap = link->ap;
40*4882a593Smuzhiyun 	struct pata_acpi *acpi = ap->private_data;
41*4882a593Smuzhiyun 	if (ACPI_HANDLE(&ap->tdev) == NULL || ata_acpi_gtm(ap, &acpi->gtm) < 0)
42*4882a593Smuzhiyun 		return -ENODEV;
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	return ata_sff_prereset(link, deadline);
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /**
48*4882a593Smuzhiyun  *	pacpi_cable_detect	-	cable type detection
49*4882a593Smuzhiyun  *	@ap: port to detect
50*4882a593Smuzhiyun  *
51*4882a593Smuzhiyun  *	Perform device specific cable detection
52*4882a593Smuzhiyun  */
53*4882a593Smuzhiyun 
pacpi_cable_detect(struct ata_port * ap)54*4882a593Smuzhiyun static int pacpi_cable_detect(struct ata_port *ap)
55*4882a593Smuzhiyun {
56*4882a593Smuzhiyun 	struct pata_acpi *acpi = ap->private_data;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	if ((acpi->mask[0] | acpi->mask[1]) & (0xF8 << ATA_SHIFT_UDMA))
59*4882a593Smuzhiyun 		return ATA_CBL_PATA80;
60*4882a593Smuzhiyun 	else
61*4882a593Smuzhiyun 		return ATA_CBL_PATA40;
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun /**
65*4882a593Smuzhiyun  *	pacpi_discover_modes	-	filter non ACPI modes
66*4882a593Smuzhiyun  *	@adev: ATA device
67*4882a593Smuzhiyun  *	@mask: proposed modes
68*4882a593Smuzhiyun  *
69*4882a593Smuzhiyun  *	Try the modes available and see which ones the ACPI method will
70*4882a593Smuzhiyun  *	set up sensibly. From this we get a mask of ACPI modes we can use
71*4882a593Smuzhiyun  */
72*4882a593Smuzhiyun 
pacpi_discover_modes(struct ata_port * ap,struct ata_device * adev)73*4882a593Smuzhiyun static unsigned long pacpi_discover_modes(struct ata_port *ap, struct ata_device *adev)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun 	struct pata_acpi *acpi = ap->private_data;
76*4882a593Smuzhiyun 	struct ata_acpi_gtm probe;
77*4882a593Smuzhiyun 	unsigned int xfer_mask;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun 	probe = acpi->gtm;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	ata_acpi_gtm(ap, &probe);
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	xfer_mask = ata_acpi_gtm_xfermask(adev, &probe);
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	if (xfer_mask & (0xF8 << ATA_SHIFT_UDMA))
86*4882a593Smuzhiyun 		ap->cbl = ATA_CBL_PATA80;
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	return xfer_mask;
89*4882a593Smuzhiyun }
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun /**
92*4882a593Smuzhiyun  *	pacpi_mode_filter	-	mode filter for ACPI
93*4882a593Smuzhiyun  *	@adev: device
94*4882a593Smuzhiyun  *	@mask: mask of valid modes
95*4882a593Smuzhiyun  *
96*4882a593Smuzhiyun  *	Filter the valid mode list according to our own specific rules, in
97*4882a593Smuzhiyun  *	this case the list of discovered valid modes obtained by ACPI probing
98*4882a593Smuzhiyun  */
99*4882a593Smuzhiyun 
pacpi_mode_filter(struct ata_device * adev,unsigned long mask)100*4882a593Smuzhiyun static unsigned long pacpi_mode_filter(struct ata_device *adev, unsigned long mask)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct pata_acpi *acpi = adev->link->ap->private_data;
103*4882a593Smuzhiyun 	return mask & acpi->mask[adev->devno];
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /**
107*4882a593Smuzhiyun  *	pacpi_set_piomode	-	set initial PIO mode data
108*4882a593Smuzhiyun  *	@ap: ATA interface
109*4882a593Smuzhiyun  *	@adev: ATA device
110*4882a593Smuzhiyun  */
111*4882a593Smuzhiyun 
pacpi_set_piomode(struct ata_port * ap,struct ata_device * adev)112*4882a593Smuzhiyun static void pacpi_set_piomode(struct ata_port *ap, struct ata_device *adev)
113*4882a593Smuzhiyun {
114*4882a593Smuzhiyun 	int unit = adev->devno;
115*4882a593Smuzhiyun 	struct pata_acpi *acpi = ap->private_data;
116*4882a593Smuzhiyun 	const struct ata_timing *t;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	if (!(acpi->gtm.flags & 0x10))
119*4882a593Smuzhiyun 		unit = 0;
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun 	/* Now stuff the nS values into the structure */
122*4882a593Smuzhiyun 	t = ata_timing_find_mode(adev->pio_mode);
123*4882a593Smuzhiyun 	acpi->gtm.drive[unit].pio = t->cycle;
124*4882a593Smuzhiyun 	ata_acpi_stm(ap, &acpi->gtm);
125*4882a593Smuzhiyun 	/* See what mode we actually got */
126*4882a593Smuzhiyun 	ata_acpi_gtm(ap, &acpi->gtm);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun /**
130*4882a593Smuzhiyun  *	pacpi_set_dmamode	-	set initial DMA mode data
131*4882a593Smuzhiyun  *	@ap: ATA interface
132*4882a593Smuzhiyun  *	@adev: ATA device
133*4882a593Smuzhiyun  */
134*4882a593Smuzhiyun 
pacpi_set_dmamode(struct ata_port * ap,struct ata_device * adev)135*4882a593Smuzhiyun static void pacpi_set_dmamode(struct ata_port *ap, struct ata_device *adev)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	int unit = adev->devno;
138*4882a593Smuzhiyun 	struct pata_acpi *acpi = ap->private_data;
139*4882a593Smuzhiyun 	const struct ata_timing *t;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun 	if (!(acpi->gtm.flags & 0x10))
142*4882a593Smuzhiyun 		unit = 0;
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	/* Now stuff the nS values into the structure */
145*4882a593Smuzhiyun 	t = ata_timing_find_mode(adev->dma_mode);
146*4882a593Smuzhiyun 	if (adev->dma_mode >= XFER_UDMA_0) {
147*4882a593Smuzhiyun 		acpi->gtm.drive[unit].dma = t->udma;
148*4882a593Smuzhiyun 		acpi->gtm.flags |= (1 << (2 * unit));
149*4882a593Smuzhiyun 	} else {
150*4882a593Smuzhiyun 		acpi->gtm.drive[unit].dma = t->cycle;
151*4882a593Smuzhiyun 		acpi->gtm.flags &= ~(1 << (2 * unit));
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun 	ata_acpi_stm(ap, &acpi->gtm);
154*4882a593Smuzhiyun 	/* See what mode we actually got */
155*4882a593Smuzhiyun 	ata_acpi_gtm(ap, &acpi->gtm);
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun /**
159*4882a593Smuzhiyun  *	pacpi_qc_issue	-	command issue
160*4882a593Smuzhiyun  *	@qc: command pending
161*4882a593Smuzhiyun  *
162*4882a593Smuzhiyun  *	Called when the libata layer is about to issue a command. We wrap
163*4882a593Smuzhiyun  *	this interface so that we can load the correct ATA timings if
164*4882a593Smuzhiyun  *	necessary.
165*4882a593Smuzhiyun  */
166*4882a593Smuzhiyun 
pacpi_qc_issue(struct ata_queued_cmd * qc)167*4882a593Smuzhiyun static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	struct ata_port *ap = qc->ap;
170*4882a593Smuzhiyun 	struct ata_device *adev = qc->dev;
171*4882a593Smuzhiyun 	struct pata_acpi *acpi = ap->private_data;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	if (acpi->gtm.flags & 0x10)
174*4882a593Smuzhiyun 		return ata_bmdma_qc_issue(qc);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	if (adev != acpi->last) {
177*4882a593Smuzhiyun 		pacpi_set_piomode(ap, adev);
178*4882a593Smuzhiyun 		if (ata_dma_enabled(adev))
179*4882a593Smuzhiyun 			pacpi_set_dmamode(ap, adev);
180*4882a593Smuzhiyun 		acpi->last = adev;
181*4882a593Smuzhiyun 	}
182*4882a593Smuzhiyun 	return ata_bmdma_qc_issue(qc);
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
185*4882a593Smuzhiyun /**
186*4882a593Smuzhiyun  *	pacpi_port_start	-	port setup
187*4882a593Smuzhiyun  *	@ap: ATA port being set up
188*4882a593Smuzhiyun  *
189*4882a593Smuzhiyun  *	Use the port_start hook to maintain private control structures
190*4882a593Smuzhiyun  */
191*4882a593Smuzhiyun 
pacpi_port_start(struct ata_port * ap)192*4882a593Smuzhiyun static int pacpi_port_start(struct ata_port *ap)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
195*4882a593Smuzhiyun 	struct pata_acpi *acpi;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	if (ACPI_HANDLE(&ap->tdev) == NULL)
198*4882a593Smuzhiyun 		return -ENODEV;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	acpi = ap->private_data = devm_kzalloc(&pdev->dev, sizeof(struct pata_acpi), GFP_KERNEL);
201*4882a593Smuzhiyun 	if (ap->private_data == NULL)
202*4882a593Smuzhiyun 		return -ENOMEM;
203*4882a593Smuzhiyun 	acpi->mask[0] = pacpi_discover_modes(ap, &ap->link.device[0]);
204*4882a593Smuzhiyun 	acpi->mask[1] = pacpi_discover_modes(ap, &ap->link.device[1]);
205*4882a593Smuzhiyun 	return ata_bmdma_port_start(ap);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun static struct scsi_host_template pacpi_sht = {
209*4882a593Smuzhiyun 	ATA_BMDMA_SHT(DRV_NAME),
210*4882a593Smuzhiyun };
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun static struct ata_port_operations pacpi_ops = {
213*4882a593Smuzhiyun 	.inherits		= &ata_bmdma_port_ops,
214*4882a593Smuzhiyun 	.qc_issue		= pacpi_qc_issue,
215*4882a593Smuzhiyun 	.cable_detect		= pacpi_cable_detect,
216*4882a593Smuzhiyun 	.mode_filter		= pacpi_mode_filter,
217*4882a593Smuzhiyun 	.set_piomode		= pacpi_set_piomode,
218*4882a593Smuzhiyun 	.set_dmamode		= pacpi_set_dmamode,
219*4882a593Smuzhiyun 	.prereset		= pacpi_pre_reset,
220*4882a593Smuzhiyun 	.port_start		= pacpi_port_start,
221*4882a593Smuzhiyun };
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun /**
225*4882a593Smuzhiyun  *	pacpi_init_one - Register ACPI ATA PCI device with kernel services
226*4882a593Smuzhiyun  *	@pdev: PCI device to register
227*4882a593Smuzhiyun  *	@ent: Entry in pacpi_pci_tbl matching with @pdev
228*4882a593Smuzhiyun  *
229*4882a593Smuzhiyun  *	Called from kernel PCI layer.
230*4882a593Smuzhiyun  *
231*4882a593Smuzhiyun  *	LOCKING:
232*4882a593Smuzhiyun  *	Inherited from PCI layer (may sleep).
233*4882a593Smuzhiyun  *
234*4882a593Smuzhiyun  *	RETURNS:
235*4882a593Smuzhiyun  *	Zero on success, or -ERRNO value.
236*4882a593Smuzhiyun  */
237*4882a593Smuzhiyun 
pacpi_init_one(struct pci_dev * pdev,const struct pci_device_id * id)238*4882a593Smuzhiyun static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
239*4882a593Smuzhiyun {
240*4882a593Smuzhiyun 	static const struct ata_port_info info = {
241*4882a593Smuzhiyun 		.flags		= ATA_FLAG_SLAVE_POSS,
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 		.pio_mask	= ATA_PIO4,
244*4882a593Smuzhiyun 		.mwdma_mask	= ATA_MWDMA2,
245*4882a593Smuzhiyun 		.udma_mask 	= ATA_UDMA6,
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 		.port_ops	= &pacpi_ops,
248*4882a593Smuzhiyun 	};
249*4882a593Smuzhiyun 	const struct ata_port_info *ppi[] = { &info, NULL };
250*4882a593Smuzhiyun 	if (pdev->vendor == PCI_VENDOR_ID_ATI) {
251*4882a593Smuzhiyun 		int rc = pcim_enable_device(pdev);
252*4882a593Smuzhiyun 		if (rc < 0)
253*4882a593Smuzhiyun 			return rc;
254*4882a593Smuzhiyun 		pcim_pin_device(pdev);
255*4882a593Smuzhiyun 	}
256*4882a593Smuzhiyun 	return ata_pci_bmdma_init_one(pdev, ppi, &pacpi_sht, NULL, 0);
257*4882a593Smuzhiyun }
258*4882a593Smuzhiyun 
259*4882a593Smuzhiyun static const struct pci_device_id pacpi_pci_tbl[] = {
260*4882a593Smuzhiyun 	{ PCI_ANY_ID,		PCI_ANY_ID,			   PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 1},
261*4882a593Smuzhiyun 	{ }	/* terminate list */
262*4882a593Smuzhiyun };
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun static struct pci_driver pacpi_pci_driver = {
265*4882a593Smuzhiyun 	.name			= DRV_NAME,
266*4882a593Smuzhiyun 	.id_table		= pacpi_pci_tbl,
267*4882a593Smuzhiyun 	.probe			= pacpi_init_one,
268*4882a593Smuzhiyun 	.remove			= ata_pci_remove_one,
269*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
270*4882a593Smuzhiyun 	.suspend		= ata_pci_device_suspend,
271*4882a593Smuzhiyun 	.resume			= ata_pci_device_resume,
272*4882a593Smuzhiyun #endif
273*4882a593Smuzhiyun };
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun module_pci_driver(pacpi_pci_driver);
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun MODULE_AUTHOR("Alan Cox");
278*4882a593Smuzhiyun MODULE_DESCRIPTION("SCSI low-level driver for ATA in ACPI mode");
279*4882a593Smuzhiyun MODULE_LICENSE("GPL");
280*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, pacpi_pci_tbl);
281*4882a593Smuzhiyun MODULE_VERSION(DRV_VERSION);
282