brintos

brintos / linux-shallow public Read only

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