xref: /OK3568_Linux_fs/kernel/drivers/ata/pata_cmd640.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * pata_cmd640.c 	- CMD640 PCI PATA for new ATA layer
4*4882a593Smuzhiyun  *			  (C) 2007 Red Hat Inc
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Based upon
7*4882a593Smuzhiyun  *  linux/drivers/ide/pci/cmd640.c		Version 1.02  Sep 01, 1996
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  *  Copyright (C) 1995-1996  Linus Torvalds & authors (see driver)
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  *	This drives only the PCI version of the controller. If you have a
12*4882a593Smuzhiyun  *	VLB one then we have enough docs to support it but you can write
13*4882a593Smuzhiyun  *	your own code.
14*4882a593Smuzhiyun  */
15*4882a593Smuzhiyun 
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/module.h>
18*4882a593Smuzhiyun #include <linux/pci.h>
19*4882a593Smuzhiyun #include <linux/blkdev.h>
20*4882a593Smuzhiyun #include <linux/delay.h>
21*4882a593Smuzhiyun #include <linux/gfp.h>
22*4882a593Smuzhiyun #include <scsi/scsi_host.h>
23*4882a593Smuzhiyun #include <linux/libata.h>
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun #define DRV_NAME "pata_cmd640"
26*4882a593Smuzhiyun #define DRV_VERSION "0.0.5"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun struct cmd640_reg {
29*4882a593Smuzhiyun 	int last;
30*4882a593Smuzhiyun 	u8 reg58[ATA_MAX_DEVICES];
31*4882a593Smuzhiyun };
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun enum {
34*4882a593Smuzhiyun 	CFR = 0x50,
35*4882a593Smuzhiyun 	CNTRL = 0x51,
36*4882a593Smuzhiyun 	CMDTIM = 0x52,
37*4882a593Smuzhiyun 	ARTIM0 = 0x53,
38*4882a593Smuzhiyun 	DRWTIM0 = 0x54,
39*4882a593Smuzhiyun 	ARTIM23 = 0x57,
40*4882a593Smuzhiyun 	DRWTIM23 = 0x58,
41*4882a593Smuzhiyun 	BRST = 0x59
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /**
45*4882a593Smuzhiyun  *	cmd640_set_piomode	-	set initial PIO mode data
46*4882a593Smuzhiyun  *	@ap: ATA port
47*4882a593Smuzhiyun  *	@adev: ATA device
48*4882a593Smuzhiyun  *
49*4882a593Smuzhiyun  *	Called to do the PIO mode setup.
50*4882a593Smuzhiyun  */
51*4882a593Smuzhiyun 
cmd640_set_piomode(struct ata_port * ap,struct ata_device * adev)52*4882a593Smuzhiyun static void cmd640_set_piomode(struct ata_port *ap, struct ata_device *adev)
53*4882a593Smuzhiyun {
54*4882a593Smuzhiyun 	struct cmd640_reg *timing = ap->private_data;
55*4882a593Smuzhiyun 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
56*4882a593Smuzhiyun 	struct ata_timing t;
57*4882a593Smuzhiyun 	const unsigned long T = 1000000 / 33;
58*4882a593Smuzhiyun 	const u8 setup_data[] = { 0x40, 0x40, 0x40, 0x80, 0x00 };
59*4882a593Smuzhiyun 	u8 reg;
60*4882a593Smuzhiyun 	int arttim = ARTIM0 + 2 * adev->devno;
61*4882a593Smuzhiyun 	struct ata_device *pair = ata_dev_pair(adev);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	if (ata_timing_compute(adev, adev->pio_mode, &t, T, 0) < 0) {
64*4882a593Smuzhiyun 		printk(KERN_ERR DRV_NAME ": mode computation failed.\n");
65*4882a593Smuzhiyun 		return;
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	/* The second channel has shared timings and the setup timing is
69*4882a593Smuzhiyun 	   messy to switch to merge it for worst case */
70*4882a593Smuzhiyun 	if (ap->port_no && pair) {
71*4882a593Smuzhiyun 		struct ata_timing p;
72*4882a593Smuzhiyun 		ata_timing_compute(pair, pair->pio_mode, &p, T, 1);
73*4882a593Smuzhiyun 		ata_timing_merge(&p, &t, &t, ATA_TIMING_SETUP);
74*4882a593Smuzhiyun 	}
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	/* Make the timings fit */
77*4882a593Smuzhiyun 	if (t.recover > 16) {
78*4882a593Smuzhiyun 		t.active += t.recover - 16;
79*4882a593Smuzhiyun 		t.recover = 16;
80*4882a593Smuzhiyun 	}
81*4882a593Smuzhiyun 	if (t.active > 16)
82*4882a593Smuzhiyun 		t.active = 16;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	/* Now convert the clocks into values we can actually stuff into
85*4882a593Smuzhiyun 	   the chip */
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (t.recover > 1)
88*4882a593Smuzhiyun 		t.recover--;	/* 640B only */
89*4882a593Smuzhiyun 	else
90*4882a593Smuzhiyun 		t.recover = 15;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	if (t.setup > 4)
93*4882a593Smuzhiyun 		t.setup = 0xC0;
94*4882a593Smuzhiyun 	else
95*4882a593Smuzhiyun 		t.setup = setup_data[t.setup];
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	if (ap->port_no == 0) {
98*4882a593Smuzhiyun 		t.active &= 0x0F;	/* 0 = 16 */
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 		/* Load setup timing */
101*4882a593Smuzhiyun 		pci_read_config_byte(pdev, arttim, &reg);
102*4882a593Smuzhiyun 		reg &= 0x3F;
103*4882a593Smuzhiyun 		reg |= t.setup;
104*4882a593Smuzhiyun 		pci_write_config_byte(pdev, arttim, reg);
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 		/* Load active/recovery */
107*4882a593Smuzhiyun 		pci_write_config_byte(pdev, arttim + 1, (t.active << 4) | t.recover);
108*4882a593Smuzhiyun 	} else {
109*4882a593Smuzhiyun 		/* Save the shared timings for channel, they will be loaded
110*4882a593Smuzhiyun 		   by qc_issue. Reloading the setup time is expensive so we
111*4882a593Smuzhiyun 		   keep a merged one loaded */
112*4882a593Smuzhiyun 		pci_read_config_byte(pdev, ARTIM23, &reg);
113*4882a593Smuzhiyun 		reg &= 0x3F;
114*4882a593Smuzhiyun 		reg |= t.setup;
115*4882a593Smuzhiyun 		pci_write_config_byte(pdev, ARTIM23, reg);
116*4882a593Smuzhiyun 		timing->reg58[adev->devno] = (t.active << 4) | t.recover;
117*4882a593Smuzhiyun 	}
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun /**
122*4882a593Smuzhiyun  *	cmd640_qc_issue	-	command preparation hook
123*4882a593Smuzhiyun  *	@qc: Command to be issued
124*4882a593Smuzhiyun  *
125*4882a593Smuzhiyun  *	Channel 1 has shared timings. We must reprogram the
126*4882a593Smuzhiyun  *	clock each drive 2/3 switch we do.
127*4882a593Smuzhiyun  */
128*4882a593Smuzhiyun 
cmd640_qc_issue(struct ata_queued_cmd * qc)129*4882a593Smuzhiyun static unsigned int cmd640_qc_issue(struct ata_queued_cmd *qc)
130*4882a593Smuzhiyun {
131*4882a593Smuzhiyun 	struct ata_port *ap = qc->ap;
132*4882a593Smuzhiyun 	struct ata_device *adev = qc->dev;
133*4882a593Smuzhiyun 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
134*4882a593Smuzhiyun 	struct cmd640_reg *timing = ap->private_data;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (ap->port_no != 0 && adev->devno != timing->last) {
137*4882a593Smuzhiyun 		pci_write_config_byte(pdev, DRWTIM23, timing->reg58[adev->devno]);
138*4882a593Smuzhiyun 		timing->last = adev->devno;
139*4882a593Smuzhiyun 	}
140*4882a593Smuzhiyun 	return ata_sff_qc_issue(qc);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun /**
144*4882a593Smuzhiyun  *	cmd640_port_start	-	port setup
145*4882a593Smuzhiyun  *	@ap: ATA port being set up
146*4882a593Smuzhiyun  *
147*4882a593Smuzhiyun  *	The CMD640 needs to maintain private data structures so we
148*4882a593Smuzhiyun  *	allocate space here.
149*4882a593Smuzhiyun  */
150*4882a593Smuzhiyun 
cmd640_port_start(struct ata_port * ap)151*4882a593Smuzhiyun static int cmd640_port_start(struct ata_port *ap)
152*4882a593Smuzhiyun {
153*4882a593Smuzhiyun 	struct pci_dev *pdev = to_pci_dev(ap->host->dev);
154*4882a593Smuzhiyun 	struct cmd640_reg *timing;
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun 	timing = devm_kzalloc(&pdev->dev, sizeof(struct cmd640_reg), GFP_KERNEL);
157*4882a593Smuzhiyun 	if (timing == NULL)
158*4882a593Smuzhiyun 		return -ENOMEM;
159*4882a593Smuzhiyun 	timing->last = -1;	/* Force a load */
160*4882a593Smuzhiyun 	ap->private_data = timing;
161*4882a593Smuzhiyun 	return 0;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
cmd640_sff_irq_check(struct ata_port * ap)164*4882a593Smuzhiyun static bool cmd640_sff_irq_check(struct ata_port *ap)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	struct pci_dev *pdev	= to_pci_dev(ap->host->dev);
167*4882a593Smuzhiyun 	int irq_reg		= ap->port_no ? ARTIM23 : CFR;
168*4882a593Smuzhiyun 	u8  irq_stat, irq_mask	= ap->port_no ? 0x10 : 0x04;
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun 	pci_read_config_byte(pdev, irq_reg, &irq_stat);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return irq_stat & irq_mask;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun static struct scsi_host_template cmd640_sht = {
176*4882a593Smuzhiyun 	ATA_PIO_SHT(DRV_NAME),
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static struct ata_port_operations cmd640_port_ops = {
180*4882a593Smuzhiyun 	.inherits	= &ata_sff_port_ops,
181*4882a593Smuzhiyun 	/* In theory xfer_noirq is not needed once we kill the prefetcher */
182*4882a593Smuzhiyun 	.sff_data_xfer	= ata_sff_data_xfer32,
183*4882a593Smuzhiyun 	.sff_irq_check	= cmd640_sff_irq_check,
184*4882a593Smuzhiyun 	.qc_issue	= cmd640_qc_issue,
185*4882a593Smuzhiyun 	.cable_detect	= ata_cable_40wire,
186*4882a593Smuzhiyun 	.set_piomode	= cmd640_set_piomode,
187*4882a593Smuzhiyun 	.port_start	= cmd640_port_start,
188*4882a593Smuzhiyun };
189*4882a593Smuzhiyun 
cmd640_hardware_init(struct pci_dev * pdev)190*4882a593Smuzhiyun static void cmd640_hardware_init(struct pci_dev *pdev)
191*4882a593Smuzhiyun {
192*4882a593Smuzhiyun 	u8 ctrl;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	/* CMD640 detected, commiserations */
195*4882a593Smuzhiyun 	pci_write_config_byte(pdev, 0x5B, 0x00);
196*4882a593Smuzhiyun 	/* PIO0 command cycles */
197*4882a593Smuzhiyun 	pci_write_config_byte(pdev, CMDTIM, 0);
198*4882a593Smuzhiyun 	/* 512 byte bursts (sector) */
199*4882a593Smuzhiyun 	pci_write_config_byte(pdev, BRST, 0x40);
200*4882a593Smuzhiyun 	/*
201*4882a593Smuzhiyun 	 * A reporter a long time ago
202*4882a593Smuzhiyun 	 * Had problems with the data fifo
203*4882a593Smuzhiyun 	 * So don't run the risk
204*4882a593Smuzhiyun 	 * Of putting crap on the disk
205*4882a593Smuzhiyun 	 * For its better just to go slow
206*4882a593Smuzhiyun 	 */
207*4882a593Smuzhiyun 	/* Do channel 0 */
208*4882a593Smuzhiyun 	pci_read_config_byte(pdev, CNTRL, &ctrl);
209*4882a593Smuzhiyun 	pci_write_config_byte(pdev, CNTRL, ctrl | 0xC0);
210*4882a593Smuzhiyun 	/* Ditto for channel 1 */
211*4882a593Smuzhiyun 	pci_read_config_byte(pdev, ARTIM23, &ctrl);
212*4882a593Smuzhiyun 	ctrl |= 0x0C;
213*4882a593Smuzhiyun 	pci_write_config_byte(pdev, ARTIM23, ctrl);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
cmd640_init_one(struct pci_dev * pdev,const struct pci_device_id * id)216*4882a593Smuzhiyun static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	static const struct ata_port_info info = {
219*4882a593Smuzhiyun 		.flags = ATA_FLAG_SLAVE_POSS,
220*4882a593Smuzhiyun 		.pio_mask = ATA_PIO4,
221*4882a593Smuzhiyun 		.port_ops = &cmd640_port_ops
222*4882a593Smuzhiyun 	};
223*4882a593Smuzhiyun 	const struct ata_port_info *ppi[] = { &info, NULL };
224*4882a593Smuzhiyun 	int rc;
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	rc = pcim_enable_device(pdev);
227*4882a593Smuzhiyun 	if (rc)
228*4882a593Smuzhiyun 		return rc;
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	cmd640_hardware_init(pdev);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun 	return ata_pci_sff_init_one(pdev, ppi, &cmd640_sht, NULL, 0);
233*4882a593Smuzhiyun }
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
cmd640_reinit_one(struct pci_dev * pdev)236*4882a593Smuzhiyun static int cmd640_reinit_one(struct pci_dev *pdev)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct ata_host *host = pci_get_drvdata(pdev);
239*4882a593Smuzhiyun 	int rc;
240*4882a593Smuzhiyun 
241*4882a593Smuzhiyun 	rc = ata_pci_device_do_resume(pdev);
242*4882a593Smuzhiyun 	if (rc)
243*4882a593Smuzhiyun 		return rc;
244*4882a593Smuzhiyun 	cmd640_hardware_init(pdev);
245*4882a593Smuzhiyun 	ata_host_resume(host);
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun #endif
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun static const struct pci_device_id cmd640[] = {
251*4882a593Smuzhiyun 	{ PCI_VDEVICE(CMD, 0x640), 0 },
252*4882a593Smuzhiyun 	{ },
253*4882a593Smuzhiyun };
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun static struct pci_driver cmd640_pci_driver = {
256*4882a593Smuzhiyun 	.name 		= DRV_NAME,
257*4882a593Smuzhiyun 	.id_table	= cmd640,
258*4882a593Smuzhiyun 	.probe 		= cmd640_init_one,
259*4882a593Smuzhiyun 	.remove		= ata_pci_remove_one,
260*4882a593Smuzhiyun #ifdef CONFIG_PM_SLEEP
261*4882a593Smuzhiyun 	.suspend	= ata_pci_device_suspend,
262*4882a593Smuzhiyun 	.resume		= cmd640_reinit_one,
263*4882a593Smuzhiyun #endif
264*4882a593Smuzhiyun };
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun module_pci_driver(cmd640_pci_driver);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun MODULE_AUTHOR("Alan Cox");
269*4882a593Smuzhiyun MODULE_DESCRIPTION("low-level driver for CMD640 PATA controllers");
270*4882a593Smuzhiyun MODULE_LICENSE("GPL");
271*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, cmd640);
272*4882a593Smuzhiyun MODULE_VERSION(DRV_VERSION);
273