109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2669a5db4SJeff Garzik /*
3669a5db4SJeff Garzik * pata_opti.c - ATI PATA for new ATA layer
4669a5db4SJeff Garzik * (C) 2005 Red Hat Inc
5669a5db4SJeff Garzik *
6669a5db4SJeff Garzik * Based on
7669a5db4SJeff Garzik * linux/drivers/ide/pci/opti621.c Version 0.7 Sept 10, 2002
8669a5db4SJeff Garzik *
9669a5db4SJeff Garzik * Copyright (C) 1996-1998 Linus Torvalds & authors (see below)
10669a5db4SJeff Garzik *
11669a5db4SJeff Garzik * Authors:
12669a5db4SJeff Garzik * Jaromir Koutek <miri@punknet.cz>,
13669a5db4SJeff Garzik * Jan Harkes <jaharkes@cwi.nl>,
14669a5db4SJeff Garzik * Mark Lord <mlord@pobox.com>
15669a5db4SJeff Garzik * Some parts of code are from ali14xx.c and from rz1000.c.
16669a5db4SJeff Garzik *
17669a5db4SJeff Garzik * Also consulted the FreeBSD prototype driver by Kevin Day to try
18669a5db4SJeff Garzik * and resolve some confusions. Further documentation can be found in
19669a5db4SJeff Garzik * Ralf Brown's interrupt list
20669a5db4SJeff Garzik *
21669a5db4SJeff Garzik * If you have other variants of the Opti range (Viper/Vendetta) please
22669a5db4SJeff Garzik * try this driver with those PCI idents and report back. For the later
23669a5db4SJeff Garzik * chips see the pata_optidma driver
24669a5db4SJeff Garzik *
25669a5db4SJeff Garzik */
26669a5db4SJeff Garzik
27669a5db4SJeff Garzik #include <linux/kernel.h>
28669a5db4SJeff Garzik #include <linux/module.h>
29669a5db4SJeff Garzik #include <linux/pci.h>
30669a5db4SJeff Garzik #include <linux/blkdev.h>
31669a5db4SJeff Garzik #include <linux/delay.h>
32669a5db4SJeff Garzik #include <scsi/scsi_host.h>
33669a5db4SJeff Garzik #include <linux/libata.h>
34669a5db4SJeff Garzik
35669a5db4SJeff Garzik #define DRV_NAME "pata_opti"
36a0fcdc02SJeff Garzik #define DRV_VERSION "0.2.9"
37669a5db4SJeff Garzik
38669a5db4SJeff Garzik enum {
39669a5db4SJeff Garzik READ_REG = 0, /* index of Read cycle timing register */
40669a5db4SJeff Garzik WRITE_REG = 1, /* index of Write cycle timing register */
41669a5db4SJeff Garzik CNTRL_REG = 3, /* index of Control register */
42669a5db4SJeff Garzik STRAP_REG = 5, /* index of Strap register */
43669a5db4SJeff Garzik MISC_REG = 6 /* index of Miscellaneous register */
44669a5db4SJeff Garzik };
45669a5db4SJeff Garzik
46669a5db4SJeff Garzik /**
47669a5db4SJeff Garzik * opti_pre_reset - probe begin
48cc0680a5STejun Heo * @link: ATA link
49d4b2bab4STejun Heo * @deadline: deadline jiffies for the operation
50669a5db4SJeff Garzik *
51669a5db4SJeff Garzik * Set up cable type and use generic probe init
52669a5db4SJeff Garzik */
53669a5db4SJeff Garzik
opti_pre_reset(struct ata_link * link,unsigned long deadline)54cc0680a5STejun Heo static int opti_pre_reset(struct ata_link *link, unsigned long deadline)
55669a5db4SJeff Garzik {
56cc0680a5STejun Heo struct ata_port *ap = link->ap;
57669a5db4SJeff Garzik struct pci_dev *pdev = to_pci_dev(ap->host->dev);
58669a5db4SJeff Garzik static const struct pci_bits opti_enable_bits[] = {
59669a5db4SJeff Garzik { 0x45, 1, 0x80, 0x00 },
60669a5db4SJeff Garzik { 0x40, 1, 0x08, 0x00 }
61669a5db4SJeff Garzik };
62669a5db4SJeff Garzik
63c961922bSAlan Cox if (!pci_test_config_bits(pdev, &opti_enable_bits[ap->port_no]))
64c961922bSAlan Cox return -ENOENT;
65d4b2bab4STejun Heo
669363c382STejun Heo return ata_sff_prereset(link, deadline);
67669a5db4SJeff Garzik }
68669a5db4SJeff Garzik
69669a5db4SJeff Garzik /**
70669a5db4SJeff Garzik * opti_write_reg - control register setup
71669a5db4SJeff Garzik * @ap: ATA port
72dee1d6f3SLee Jones * @val: value
73669a5db4SJeff Garzik * @reg: control register number
74669a5db4SJeff Garzik *
75669a5db4SJeff Garzik * The Opti uses magic 'trapdoor' register accesses to do configuration
76669a5db4SJeff Garzik * rather than using PCI space as other controllers do. The double inw
77669a5db4SJeff Garzik * on the error register activates configuration mode. We can then write
78669a5db4SJeff Garzik * the control register
79669a5db4SJeff Garzik */
80669a5db4SJeff Garzik
opti_write_reg(struct ata_port * ap,u8 val,int reg)81669a5db4SJeff Garzik static void opti_write_reg(struct ata_port *ap, u8 val, int reg)
82669a5db4SJeff Garzik {
830d5ff566STejun Heo void __iomem *regio = ap->ioaddr.cmd_addr;
84669a5db4SJeff Garzik
85669a5db4SJeff Garzik /* These 3 unlock the control register access */
860d5ff566STejun Heo ioread16(regio + 1);
870d5ff566STejun Heo ioread16(regio + 1);
880d5ff566STejun Heo iowrite8(3, regio + 2);
89669a5db4SJeff Garzik
90669a5db4SJeff Garzik /* Do the I/O */
910d5ff566STejun Heo iowrite8(val, regio + reg);
92669a5db4SJeff Garzik
93669a5db4SJeff Garzik /* Relock */
940d5ff566STejun Heo iowrite8(0x83, regio + 2);
95669a5db4SJeff Garzik }
96669a5db4SJeff Garzik
97669a5db4SJeff Garzik /**
98669a5db4SJeff Garzik * opti_set_piomode - set initial PIO mode data
99669a5db4SJeff Garzik * @ap: ATA interface
100669a5db4SJeff Garzik * @adev: ATA device
101669a5db4SJeff Garzik *
102669a5db4SJeff Garzik * Called to do the PIO mode setup. Timing numbers are taken from
103669a5db4SJeff Garzik * the FreeBSD driver then pre computed to keep the code clean. There
104669a5db4SJeff Garzik * are two tables depending on the hardware clock speed.
105669a5db4SJeff Garzik */
106669a5db4SJeff Garzik
opti_set_piomode(struct ata_port * ap,struct ata_device * adev)107669a5db4SJeff Garzik static void opti_set_piomode(struct ata_port *ap, struct ata_device *adev)
108669a5db4SJeff Garzik {
109669a5db4SJeff Garzik struct ata_device *pair = ata_dev_pair(adev);
110669a5db4SJeff Garzik int clock;
111669a5db4SJeff Garzik int pio = adev->pio_mode - XFER_PIO_0;
1120d5ff566STejun Heo void __iomem *regio = ap->ioaddr.cmd_addr;
113669a5db4SJeff Garzik u8 addr;
114669a5db4SJeff Garzik
115669a5db4SJeff Garzik /* Address table precomputed with prefetch off and a DCLK of 2 */
116669a5db4SJeff Garzik static const u8 addr_timing[2][5] = {
117669a5db4SJeff Garzik { 0x30, 0x20, 0x20, 0x10, 0x10 },
118669a5db4SJeff Garzik { 0x20, 0x20, 0x10, 0x10, 0x10 }
119669a5db4SJeff Garzik };
120669a5db4SJeff Garzik static const u8 data_rec_timing[2][5] = {
121669a5db4SJeff Garzik { 0x6B, 0x56, 0x42, 0x32, 0x31 },
122669a5db4SJeff Garzik { 0x58, 0x44, 0x32, 0x22, 0x21 }
123669a5db4SJeff Garzik };
124669a5db4SJeff Garzik
1250d5ff566STejun Heo iowrite8(0xff, regio + 5);
1260d5ff566STejun Heo clock = ioread16(regio + 5) & 1;
127669a5db4SJeff Garzik
128669a5db4SJeff Garzik /*
129669a5db4SJeff Garzik * As with many controllers the address setup time is shared
130669a5db4SJeff Garzik * and must suit both devices if present.
131669a5db4SJeff Garzik */
132669a5db4SJeff Garzik
133669a5db4SJeff Garzik addr = addr_timing[clock][pio];
134669a5db4SJeff Garzik if (pair) {
135669a5db4SJeff Garzik /* Hardware constraint */
136669a5db4SJeff Garzik u8 pair_addr = addr_timing[clock][pair->pio_mode - XFER_PIO_0];
137669a5db4SJeff Garzik if (pair_addr > addr)
138669a5db4SJeff Garzik addr = pair_addr;
139669a5db4SJeff Garzik }
140669a5db4SJeff Garzik
141669a5db4SJeff Garzik /* Commence primary programming sequence */
142669a5db4SJeff Garzik opti_write_reg(ap, adev->devno, MISC_REG);
143669a5db4SJeff Garzik opti_write_reg(ap, data_rec_timing[clock][pio], READ_REG);
144669a5db4SJeff Garzik opti_write_reg(ap, data_rec_timing[clock][pio], WRITE_REG);
145669a5db4SJeff Garzik opti_write_reg(ap, addr, MISC_REG);
146669a5db4SJeff Garzik
147669a5db4SJeff Garzik /* Programming sequence complete, override strapping */
148669a5db4SJeff Garzik opti_write_reg(ap, 0x85, CNTRL_REG);
149669a5db4SJeff Garzik }
150669a5db4SJeff Garzik
151*25df73d9SBart Van Assche static const struct scsi_host_template opti_sht = {
15268d1d07bSTejun Heo ATA_PIO_SHT(DRV_NAME),
153669a5db4SJeff Garzik };
154669a5db4SJeff Garzik
155669a5db4SJeff Garzik static struct ata_port_operations opti_port_ops = {
156029cfd6bSTejun Heo .inherits = &ata_sff_port_ops,
157a0fcdc02SJeff Garzik .cable_detect = ata_cable_40wire,
158029cfd6bSTejun Heo .set_piomode = opti_set_piomode,
159a1efdabaSTejun Heo .prereset = opti_pre_reset,
160669a5db4SJeff Garzik };
161669a5db4SJeff Garzik
opti_init_one(struct pci_dev * dev,const struct pci_device_id * id)162669a5db4SJeff Garzik static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id)
163669a5db4SJeff Garzik {
1641626aeb8STejun Heo static const struct ata_port_info info = {
1651d2808fdSJeff Garzik .flags = ATA_FLAG_SLAVE_POSS,
16614bdef98SErik Inge Bolsø .pio_mask = ATA_PIO4,
167669a5db4SJeff Garzik .port_ops = &opti_port_ops
168669a5db4SJeff Garzik };
1691626aeb8STejun Heo const struct ata_port_info *ppi[] = { &info, NULL };
170669a5db4SJeff Garzik
17106296a1eSJoe Perches ata_print_version_once(&dev->dev, DRV_VERSION);
172669a5db4SJeff Garzik
17316ea0fc9SAlan Cox return ata_pci_sff_init_one(dev, ppi, &opti_sht, NULL, 0);
174669a5db4SJeff Garzik }
175669a5db4SJeff Garzik
176669a5db4SJeff Garzik static const struct pci_device_id opti[] = {
1772d2744fcSJeff Garzik { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C621), 0 },
1782d2744fcSJeff Garzik { PCI_VDEVICE(OPTI, PCI_DEVICE_ID_OPTI_82C825), 1 },
1792d2744fcSJeff Garzik
1802d2744fcSJeff Garzik { },
181669a5db4SJeff Garzik };
182669a5db4SJeff Garzik
183669a5db4SJeff Garzik static struct pci_driver opti_pci_driver = {
184669a5db4SJeff Garzik .name = DRV_NAME,
185669a5db4SJeff Garzik .id_table = opti,
186669a5db4SJeff Garzik .probe = opti_init_one,
18730ced0f0SAlan .remove = ata_pci_remove_one,
18858eb8cd5SBartlomiej Zolnierkiewicz #ifdef CONFIG_PM_SLEEP
18930ced0f0SAlan .suspend = ata_pci_device_suspend,
19030ced0f0SAlan .resume = ata_pci_device_resume,
191438ac6d5STejun Heo #endif
192669a5db4SJeff Garzik };
193669a5db4SJeff Garzik
1942fc75da0SAxel Lin module_pci_driver(opti_pci_driver);
195669a5db4SJeff Garzik
196669a5db4SJeff Garzik MODULE_AUTHOR("Alan Cox");
197669a5db4SJeff Garzik MODULE_DESCRIPTION("low-level driver for Opti 621/621X");
198669a5db4SJeff Garzik MODULE_LICENSE("GPL");
199669a5db4SJeff Garzik MODULE_DEVICE_TABLE(pci, opti);
200669a5db4SJeff Garzik MODULE_VERSION(DRV_VERSION);
201