cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sata_vsc.c (11412B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  sata_vsc.c - Vitesse VSC7174 4 port DPA SATA
      4 *
      5 *  Maintained by:  Jeremy Higdon @ SGI
      6 * 		    Please ALWAYS copy linux-ide@vger.kernel.org
      7 *		    on emails.
      8 *
      9 *  Copyright 2004 SGI
     10 *
     11 *  Bits from Jeff Garzik, Copyright RedHat, Inc.
     12 *
     13 *  libata documentation is available via 'make {ps|pdf}docs',
     14 *  as Documentation/driver-api/libata.rst
     15 *
     16 *  Vitesse hardware documentation presumably available under NDA.
     17 *  Intel 31244 (same hardware interface) documentation presumably
     18 *  available from http://developer.intel.com/
     19 */
     20
     21#include <linux/kernel.h>
     22#include <linux/module.h>
     23#include <linux/pci.h>
     24#include <linux/blkdev.h>
     25#include <linux/delay.h>
     26#include <linux/interrupt.h>
     27#include <linux/dma-mapping.h>
     28#include <linux/device.h>
     29#include <scsi/scsi_host.h>
     30#include <linux/libata.h>
     31
     32#define DRV_NAME	"sata_vsc"
     33#define DRV_VERSION	"2.3"
     34
     35enum {
     36	VSC_MMIO_BAR			= 0,
     37
     38	/* Interrupt register offsets (from chip base address) */
     39	VSC_SATA_INT_STAT_OFFSET	= 0x00,
     40	VSC_SATA_INT_MASK_OFFSET	= 0x04,
     41
     42	/* Taskfile registers offsets */
     43	VSC_SATA_TF_CMD_OFFSET		= 0x00,
     44	VSC_SATA_TF_DATA_OFFSET		= 0x00,
     45	VSC_SATA_TF_ERROR_OFFSET	= 0x04,
     46	VSC_SATA_TF_FEATURE_OFFSET	= 0x06,
     47	VSC_SATA_TF_NSECT_OFFSET	= 0x08,
     48	VSC_SATA_TF_LBAL_OFFSET		= 0x0c,
     49	VSC_SATA_TF_LBAM_OFFSET		= 0x10,
     50	VSC_SATA_TF_LBAH_OFFSET		= 0x14,
     51	VSC_SATA_TF_DEVICE_OFFSET	= 0x18,
     52	VSC_SATA_TF_STATUS_OFFSET	= 0x1c,
     53	VSC_SATA_TF_COMMAND_OFFSET	= 0x1d,
     54	VSC_SATA_TF_ALTSTATUS_OFFSET	= 0x28,
     55	VSC_SATA_TF_CTL_OFFSET		= 0x29,
     56
     57	/* DMA base */
     58	VSC_SATA_UP_DESCRIPTOR_OFFSET	= 0x64,
     59	VSC_SATA_UP_DATA_BUFFER_OFFSET	= 0x6C,
     60	VSC_SATA_DMA_CMD_OFFSET		= 0x70,
     61
     62	/* SCRs base */
     63	VSC_SATA_SCR_STATUS_OFFSET	= 0x100,
     64	VSC_SATA_SCR_ERROR_OFFSET	= 0x104,
     65	VSC_SATA_SCR_CONTROL_OFFSET	= 0x108,
     66
     67	/* Port stride */
     68	VSC_SATA_PORT_OFFSET		= 0x200,
     69
     70	/* Error interrupt status bit offsets */
     71	VSC_SATA_INT_ERROR_CRC		= 0x40,
     72	VSC_SATA_INT_ERROR_T		= 0x20,
     73	VSC_SATA_INT_ERROR_P		= 0x10,
     74	VSC_SATA_INT_ERROR_R		= 0x8,
     75	VSC_SATA_INT_ERROR_E		= 0x4,
     76	VSC_SATA_INT_ERROR_M		= 0x2,
     77	VSC_SATA_INT_PHY_CHANGE		= 0x1,
     78	VSC_SATA_INT_ERROR = (VSC_SATA_INT_ERROR_CRC  | VSC_SATA_INT_ERROR_T | \
     79			      VSC_SATA_INT_ERROR_P    | VSC_SATA_INT_ERROR_R | \
     80			      VSC_SATA_INT_ERROR_E    | VSC_SATA_INT_ERROR_M | \
     81			      VSC_SATA_INT_PHY_CHANGE),
     82};
     83
     84static int vsc_sata_scr_read(struct ata_link *link,
     85			     unsigned int sc_reg, u32 *val)
     86{
     87	if (sc_reg > SCR_CONTROL)
     88		return -EINVAL;
     89	*val = readl(link->ap->ioaddr.scr_addr + (sc_reg * 4));
     90	return 0;
     91}
     92
     93
     94static int vsc_sata_scr_write(struct ata_link *link,
     95			      unsigned int sc_reg, u32 val)
     96{
     97	if (sc_reg > SCR_CONTROL)
     98		return -EINVAL;
     99	writel(val, link->ap->ioaddr.scr_addr + (sc_reg * 4));
    100	return 0;
    101}
    102
    103
    104static void vsc_freeze(struct ata_port *ap)
    105{
    106	void __iomem *mask_addr;
    107
    108	mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
    109		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
    110
    111	writeb(0, mask_addr);
    112}
    113
    114
    115static void vsc_thaw(struct ata_port *ap)
    116{
    117	void __iomem *mask_addr;
    118
    119	mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
    120		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
    121
    122	writeb(0xff, mask_addr);
    123}
    124
    125
    126static void vsc_intr_mask_update(struct ata_port *ap, u8 ctl)
    127{
    128	void __iomem *mask_addr;
    129	u8 mask;
    130
    131	mask_addr = ap->host->iomap[VSC_MMIO_BAR] +
    132		VSC_SATA_INT_MASK_OFFSET + ap->port_no;
    133	mask = readb(mask_addr);
    134	if (ctl & ATA_NIEN)
    135		mask |= 0x80;
    136	else
    137		mask &= 0x7F;
    138	writeb(mask, mask_addr);
    139}
    140
    141
    142static void vsc_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
    143{
    144	struct ata_ioports *ioaddr = &ap->ioaddr;
    145	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
    146
    147	/*
    148	 * The only thing the ctl register is used for is SRST.
    149	 * That is not enabled or disabled via tf_load.
    150	 * However, if ATA_NIEN is changed, then we need to change
    151	 * the interrupt register.
    152	 */
    153	if ((tf->ctl & ATA_NIEN) != (ap->last_ctl & ATA_NIEN)) {
    154		ap->last_ctl = tf->ctl;
    155		vsc_intr_mask_update(ap, tf->ctl & ATA_NIEN);
    156	}
    157	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
    158		writew(tf->feature | (((u16)tf->hob_feature) << 8),
    159		       ioaddr->feature_addr);
    160		writew(tf->nsect | (((u16)tf->hob_nsect) << 8),
    161		       ioaddr->nsect_addr);
    162		writew(tf->lbal | (((u16)tf->hob_lbal) << 8),
    163		       ioaddr->lbal_addr);
    164		writew(tf->lbam | (((u16)tf->hob_lbam) << 8),
    165		       ioaddr->lbam_addr);
    166		writew(tf->lbah | (((u16)tf->hob_lbah) << 8),
    167		       ioaddr->lbah_addr);
    168	} else if (is_addr) {
    169		writew(tf->feature, ioaddr->feature_addr);
    170		writew(tf->nsect, ioaddr->nsect_addr);
    171		writew(tf->lbal, ioaddr->lbal_addr);
    172		writew(tf->lbam, ioaddr->lbam_addr);
    173		writew(tf->lbah, ioaddr->lbah_addr);
    174	}
    175
    176	if (tf->flags & ATA_TFLAG_DEVICE)
    177		writeb(tf->device, ioaddr->device_addr);
    178
    179	ata_wait_idle(ap);
    180}
    181
    182
    183static void vsc_sata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
    184{
    185	struct ata_ioports *ioaddr = &ap->ioaddr;
    186	u16 nsect, lbal, lbam, lbah, error;
    187
    188	tf->status = ata_sff_check_status(ap);
    189	tf->device = readw(ioaddr->device_addr);
    190	error = readw(ioaddr->error_addr);
    191	nsect = readw(ioaddr->nsect_addr);
    192	lbal = readw(ioaddr->lbal_addr);
    193	lbam = readw(ioaddr->lbam_addr);
    194	lbah = readw(ioaddr->lbah_addr);
    195
    196	tf->error = error;
    197	tf->nsect = nsect;
    198	tf->lbal = lbal;
    199	tf->lbam = lbam;
    200	tf->lbah = lbah;
    201
    202	if (tf->flags & ATA_TFLAG_LBA48) {
    203		tf->hob_feature = error >> 8;
    204		tf->hob_nsect = nsect >> 8;
    205		tf->hob_lbal = lbal >> 8;
    206		tf->hob_lbam = lbam >> 8;
    207		tf->hob_lbah = lbah >> 8;
    208	}
    209}
    210
    211static inline void vsc_error_intr(u8 port_status, struct ata_port *ap)
    212{
    213	if (port_status & (VSC_SATA_INT_PHY_CHANGE | VSC_SATA_INT_ERROR_M))
    214		ata_port_freeze(ap);
    215	else
    216		ata_port_abort(ap);
    217}
    218
    219static void vsc_port_intr(u8 port_status, struct ata_port *ap)
    220{
    221	struct ata_queued_cmd *qc;
    222	int handled = 0;
    223
    224	if (unlikely(port_status & VSC_SATA_INT_ERROR)) {
    225		vsc_error_intr(port_status, ap);
    226		return;
    227	}
    228
    229	qc = ata_qc_from_tag(ap, ap->link.active_tag);
    230	if (qc && likely(!(qc->tf.flags & ATA_TFLAG_POLLING)))
    231		handled = ata_bmdma_port_intr(ap, qc);
    232
    233	/* We received an interrupt during a polled command,
    234	 * or some other spurious condition.  Interrupt reporting
    235	 * with this hardware is fairly reliable so it is safe to
    236	 * simply clear the interrupt
    237	 */
    238	if (unlikely(!handled))
    239		ap->ops->sff_check_status(ap);
    240}
    241
    242/*
    243 * vsc_sata_interrupt
    244 *
    245 * Read the interrupt register and process for the devices that have
    246 * them pending.
    247 */
    248static irqreturn_t vsc_sata_interrupt(int irq, void *dev_instance)
    249{
    250	struct ata_host *host = dev_instance;
    251	unsigned int i;
    252	unsigned int handled = 0;
    253	u32 status;
    254
    255	status = readl(host->iomap[VSC_MMIO_BAR] + VSC_SATA_INT_STAT_OFFSET);
    256
    257	if (unlikely(status == 0xffffffff || status == 0)) {
    258		if (status)
    259			dev_err(host->dev,
    260				": IRQ status == 0xffffffff, PCI fault or device removal?\n");
    261		goto out;
    262	}
    263
    264	spin_lock(&host->lock);
    265
    266	for (i = 0; i < host->n_ports; i++) {
    267		u8 port_status = (status >> (8 * i)) & 0xff;
    268		if (port_status) {
    269			vsc_port_intr(port_status, host->ports[i]);
    270			handled++;
    271		}
    272	}
    273
    274	spin_unlock(&host->lock);
    275out:
    276	return IRQ_RETVAL(handled);
    277}
    278
    279
    280static struct scsi_host_template vsc_sata_sht = {
    281	ATA_BMDMA_SHT(DRV_NAME),
    282};
    283
    284
    285static struct ata_port_operations vsc_sata_ops = {
    286	.inherits		= &ata_bmdma_port_ops,
    287	/* The IRQ handling is not quite standard SFF behaviour so we
    288	   cannot use the default lost interrupt handler */
    289	.lost_interrupt		= ATA_OP_NULL,
    290	.sff_tf_load		= vsc_sata_tf_load,
    291	.sff_tf_read		= vsc_sata_tf_read,
    292	.freeze			= vsc_freeze,
    293	.thaw			= vsc_thaw,
    294	.scr_read		= vsc_sata_scr_read,
    295	.scr_write		= vsc_sata_scr_write,
    296};
    297
    298static void vsc_sata_setup_port(struct ata_ioports *port, void __iomem *base)
    299{
    300	port->cmd_addr		= base + VSC_SATA_TF_CMD_OFFSET;
    301	port->data_addr		= base + VSC_SATA_TF_DATA_OFFSET;
    302	port->error_addr	= base + VSC_SATA_TF_ERROR_OFFSET;
    303	port->feature_addr	= base + VSC_SATA_TF_FEATURE_OFFSET;
    304	port->nsect_addr	= base + VSC_SATA_TF_NSECT_OFFSET;
    305	port->lbal_addr		= base + VSC_SATA_TF_LBAL_OFFSET;
    306	port->lbam_addr		= base + VSC_SATA_TF_LBAM_OFFSET;
    307	port->lbah_addr		= base + VSC_SATA_TF_LBAH_OFFSET;
    308	port->device_addr	= base + VSC_SATA_TF_DEVICE_OFFSET;
    309	port->status_addr	= base + VSC_SATA_TF_STATUS_OFFSET;
    310	port->command_addr	= base + VSC_SATA_TF_COMMAND_OFFSET;
    311	port->altstatus_addr	= base + VSC_SATA_TF_ALTSTATUS_OFFSET;
    312	port->ctl_addr		= base + VSC_SATA_TF_CTL_OFFSET;
    313	port->bmdma_addr	= base + VSC_SATA_DMA_CMD_OFFSET;
    314	port->scr_addr		= base + VSC_SATA_SCR_STATUS_OFFSET;
    315	writel(0, base + VSC_SATA_UP_DESCRIPTOR_OFFSET);
    316	writel(0, base + VSC_SATA_UP_DATA_BUFFER_OFFSET);
    317}
    318
    319
    320static int vsc_sata_init_one(struct pci_dev *pdev,
    321			     const struct pci_device_id *ent)
    322{
    323	static const struct ata_port_info pi = {
    324		.flags		= ATA_FLAG_SATA,
    325		.pio_mask	= ATA_PIO4,
    326		.mwdma_mask	= ATA_MWDMA2,
    327		.udma_mask	= ATA_UDMA6,
    328		.port_ops	= &vsc_sata_ops,
    329	};
    330	const struct ata_port_info *ppi[] = { &pi, NULL };
    331	struct ata_host *host;
    332	void __iomem *mmio_base;
    333	int i, rc;
    334	u8 cls;
    335
    336	ata_print_version_once(&pdev->dev, DRV_VERSION);
    337
    338	/* allocate host */
    339	host = ata_host_alloc_pinfo(&pdev->dev, ppi, 4);
    340	if (!host)
    341		return -ENOMEM;
    342
    343	rc = pcim_enable_device(pdev);
    344	if (rc)
    345		return rc;
    346
    347	/* check if we have needed resource mapped */
    348	if (pci_resource_len(pdev, 0) == 0)
    349		return -ENODEV;
    350
    351	/* map IO regions and initialize host accordingly */
    352	rc = pcim_iomap_regions(pdev, 1 << VSC_MMIO_BAR, DRV_NAME);
    353	if (rc == -EBUSY)
    354		pcim_pin_device(pdev);
    355	if (rc)
    356		return rc;
    357	host->iomap = pcim_iomap_table(pdev);
    358
    359	mmio_base = host->iomap[VSC_MMIO_BAR];
    360
    361	for (i = 0; i < host->n_ports; i++) {
    362		struct ata_port *ap = host->ports[i];
    363		unsigned int offset = (i + 1) * VSC_SATA_PORT_OFFSET;
    364
    365		vsc_sata_setup_port(&ap->ioaddr, mmio_base + offset);
    366
    367		ata_port_pbar_desc(ap, VSC_MMIO_BAR, -1, "mmio");
    368		ata_port_pbar_desc(ap, VSC_MMIO_BAR, offset, "port");
    369	}
    370
    371	/*
    372	 * Use 32 bit DMA mask, because 64 bit address support is poor.
    373	 */
    374	rc = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
    375	if (rc)
    376		return rc;
    377
    378	/*
    379	 * Due to a bug in the chip, the default cache line size can't be
    380	 * used (unless the default is non-zero).
    381	 */
    382	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cls);
    383	if (cls == 0x00)
    384		pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x80);
    385
    386	if (pci_enable_msi(pdev) == 0)
    387		pci_intx(pdev, 0);
    388
    389	/*
    390	 * Config offset 0x98 is "Extended Control and Status Register 0"
    391	 * Default value is (1 << 28).  All bits except bit 28 are reserved in
    392	 * DPA mode.  If bit 28 is set, LED 0 reflects all ports' activity.
    393	 * If bit 28 is clear, each port has its own LED.
    394	 */
    395	pci_write_config_dword(pdev, 0x98, 0);
    396
    397	pci_set_master(pdev);
    398	return ata_host_activate(host, pdev->irq, vsc_sata_interrupt,
    399				 IRQF_SHARED, &vsc_sata_sht);
    400}
    401
    402static const struct pci_device_id vsc_sata_pci_tbl[] = {
    403	{ PCI_VENDOR_ID_VITESSE, 0x7174,
    404	  PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
    405	{ PCI_VENDOR_ID_INTEL, 0x3200,
    406	  PCI_ANY_ID, PCI_ANY_ID, 0x10600, 0xFFFFFF, 0 },
    407
    408	{ }	/* terminate list */
    409};
    410
    411static struct pci_driver vsc_sata_pci_driver = {
    412	.name			= DRV_NAME,
    413	.id_table		= vsc_sata_pci_tbl,
    414	.probe			= vsc_sata_init_one,
    415	.remove			= ata_pci_remove_one,
    416};
    417
    418module_pci_driver(vsc_sata_pci_driver);
    419
    420MODULE_AUTHOR("Jeremy Higdon");
    421MODULE_DESCRIPTION("low-level driver for Vitesse VSC7174 SATA controller");
    422MODULE_LICENSE("GPL");
    423MODULE_DEVICE_TABLE(pci, vsc_sata_pci_tbl);
    424MODULE_VERSION(DRV_VERSION);