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_uli.c (6045B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  sata_uli.c - ULi Electronics SATA
      4 *
      5 *  libata documentation is available via 'make {ps|pdf}docs',
      6 *  as Documentation/driver-api/libata.rst
      7 *
      8 *  Hardware documentation available under NDA.
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/module.h>
     13#include <linux/gfp.h>
     14#include <linux/pci.h>
     15#include <linux/blkdev.h>
     16#include <linux/delay.h>
     17#include <linux/interrupt.h>
     18#include <linux/device.h>
     19#include <scsi/scsi_host.h>
     20#include <linux/libata.h>
     21
     22#define DRV_NAME	"sata_uli"
     23#define DRV_VERSION	"1.3"
     24
     25enum {
     26	uli_5289		= 0,
     27	uli_5287		= 1,
     28	uli_5281		= 2,
     29
     30	uli_max_ports		= 4,
     31
     32	/* PCI configuration registers */
     33	ULI5287_BASE		= 0x90, /* sata0 phy SCR registers */
     34	ULI5287_OFFS		= 0x10, /* offset from sata0->sata1 phy regs */
     35	ULI5281_BASE		= 0x60, /* sata0 phy SCR  registers */
     36	ULI5281_OFFS		= 0x60, /* offset from sata0->sata1 phy regs */
     37};
     38
     39struct uli_priv {
     40	unsigned int		scr_cfg_addr[uli_max_ports];
     41};
     42
     43static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
     44static int uli_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val);
     45static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val);
     46
     47static const struct pci_device_id uli_pci_tbl[] = {
     48	{ PCI_VDEVICE(AL, 0x5289), uli_5289 },
     49	{ PCI_VDEVICE(AL, 0x5287), uli_5287 },
     50	{ PCI_VDEVICE(AL, 0x5281), uli_5281 },
     51
     52	{ }	/* terminate list */
     53};
     54
     55static struct pci_driver uli_pci_driver = {
     56	.name			= DRV_NAME,
     57	.id_table		= uli_pci_tbl,
     58	.probe			= uli_init_one,
     59	.remove			= ata_pci_remove_one,
     60};
     61
     62static struct scsi_host_template uli_sht = {
     63	ATA_BMDMA_SHT(DRV_NAME),
     64};
     65
     66static struct ata_port_operations uli_ops = {
     67	.inherits		= &ata_bmdma_port_ops,
     68	.scr_read		= uli_scr_read,
     69	.scr_write		= uli_scr_write,
     70	.hardreset		= ATA_OP_NULL,
     71};
     72
     73static const struct ata_port_info uli_port_info = {
     74	.flags		= ATA_FLAG_SATA | ATA_FLAG_IGN_SIMPLEX,
     75	.pio_mask       = ATA_PIO4,
     76	.udma_mask      = ATA_UDMA6,
     77	.port_ops       = &uli_ops,
     78};
     79
     80
     81MODULE_AUTHOR("Peer Chen");
     82MODULE_DESCRIPTION("low-level driver for ULi Electronics SATA controller");
     83MODULE_LICENSE("GPL");
     84MODULE_DEVICE_TABLE(pci, uli_pci_tbl);
     85MODULE_VERSION(DRV_VERSION);
     86
     87static unsigned int get_scr_cfg_addr(struct ata_port *ap, unsigned int sc_reg)
     88{
     89	struct uli_priv *hpriv = ap->host->private_data;
     90	return hpriv->scr_cfg_addr[ap->port_no] + (4 * sc_reg);
     91}
     92
     93static u32 uli_scr_cfg_read(struct ata_link *link, unsigned int sc_reg)
     94{
     95	struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
     96	unsigned int cfg_addr = get_scr_cfg_addr(link->ap, sc_reg);
     97	u32 val;
     98
     99	pci_read_config_dword(pdev, cfg_addr, &val);
    100	return val;
    101}
    102
    103static void uli_scr_cfg_write(struct ata_link *link, unsigned int scr, u32 val)
    104{
    105	struct pci_dev *pdev = to_pci_dev(link->ap->host->dev);
    106	unsigned int cfg_addr = get_scr_cfg_addr(link->ap, scr);
    107
    108	pci_write_config_dword(pdev, cfg_addr, val);
    109}
    110
    111static int uli_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
    112{
    113	if (sc_reg > SCR_CONTROL)
    114		return -EINVAL;
    115
    116	*val = uli_scr_cfg_read(link, sc_reg);
    117	return 0;
    118}
    119
    120static int uli_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val)
    121{
    122	if (sc_reg > SCR_CONTROL) //SCR_CONTROL=2, SCR_ERROR=1, SCR_STATUS=0
    123		return -EINVAL;
    124
    125	uli_scr_cfg_write(link, sc_reg, val);
    126	return 0;
    127}
    128
    129static int uli_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
    130{
    131	const struct ata_port_info *ppi[] = { &uli_port_info, NULL };
    132	unsigned int board_idx = (unsigned int) ent->driver_data;
    133	struct ata_host *host;
    134	struct uli_priv *hpriv;
    135	void __iomem * const *iomap;
    136	struct ata_ioports *ioaddr;
    137	int n_ports, rc;
    138
    139	ata_print_version_once(&pdev->dev, DRV_VERSION);
    140
    141	rc = pcim_enable_device(pdev);
    142	if (rc)
    143		return rc;
    144
    145	n_ports = 2;
    146	if (board_idx == uli_5287)
    147		n_ports = 4;
    148
    149	/* allocate the host */
    150	host = ata_host_alloc_pinfo(&pdev->dev, ppi, n_ports);
    151	if (!host)
    152		return -ENOMEM;
    153
    154	hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
    155	if (!hpriv)
    156		return -ENOMEM;
    157	host->private_data = hpriv;
    158
    159	/* the first two ports are standard SFF */
    160	rc = ata_pci_sff_init_host(host);
    161	if (rc)
    162		return rc;
    163
    164	ata_pci_bmdma_init(host);
    165
    166	iomap = host->iomap;
    167
    168	switch (board_idx) {
    169	case uli_5287:
    170		/* If there are four, the last two live right after
    171		 * the standard SFF ports.
    172		 */
    173		hpriv->scr_cfg_addr[0] = ULI5287_BASE;
    174		hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
    175
    176		ioaddr = &host->ports[2]->ioaddr;
    177		ioaddr->cmd_addr = iomap[0] + 8;
    178		ioaddr->altstatus_addr =
    179		ioaddr->ctl_addr = (void __iomem *)
    180			((unsigned long)iomap[1] | ATA_PCI_CTL_OFS) + 4;
    181		ioaddr->bmdma_addr = iomap[4] + 16;
    182		hpriv->scr_cfg_addr[2] = ULI5287_BASE + ULI5287_OFFS*4;
    183		ata_sff_std_ports(ioaddr);
    184
    185		ata_port_desc(host->ports[2],
    186			"cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
    187			(unsigned long long)pci_resource_start(pdev, 0) + 8,
    188			((unsigned long long)pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS) + 4,
    189			(unsigned long long)pci_resource_start(pdev, 4) + 16);
    190
    191		ioaddr = &host->ports[3]->ioaddr;
    192		ioaddr->cmd_addr = iomap[2] + 8;
    193		ioaddr->altstatus_addr =
    194		ioaddr->ctl_addr = (void __iomem *)
    195			((unsigned long)iomap[3] | ATA_PCI_CTL_OFS) + 4;
    196		ioaddr->bmdma_addr = iomap[4] + 24;
    197		hpriv->scr_cfg_addr[3] = ULI5287_BASE + ULI5287_OFFS*5;
    198		ata_sff_std_ports(ioaddr);
    199
    200		ata_port_desc(host->ports[2],
    201			"cmd 0x%llx ctl 0x%llx bmdma 0x%llx",
    202			(unsigned long long)pci_resource_start(pdev, 2) + 9,
    203			((unsigned long long)pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS) + 4,
    204			(unsigned long long)pci_resource_start(pdev, 4) + 24);
    205
    206		break;
    207
    208	case uli_5289:
    209		hpriv->scr_cfg_addr[0] = ULI5287_BASE;
    210		hpriv->scr_cfg_addr[1] = ULI5287_BASE + ULI5287_OFFS;
    211		break;
    212
    213	case uli_5281:
    214		hpriv->scr_cfg_addr[0] = ULI5281_BASE;
    215		hpriv->scr_cfg_addr[1] = ULI5281_BASE + ULI5281_OFFS;
    216		break;
    217
    218	default:
    219		BUG();
    220		break;
    221	}
    222
    223	pci_set_master(pdev);
    224	pci_intx(pdev, 1);
    225	return ata_host_activate(host, pdev->irq, ata_bmdma_interrupt,
    226				 IRQF_SHARED, &uli_sht);
    227}
    228
    229module_pci_driver(uli_pci_driver);