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

spi-cavium-thunderx.c (2776B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Cavium ThunderX SPI driver.
      4 *
      5 * Copyright (C) 2016 Cavium Inc.
      6 * Authors: Jan Glauber <jglauber@cavium.com>
      7 */
      8
      9#include <linux/module.h>
     10#include <linux/pci.h>
     11#include <linux/spi/spi.h>
     12
     13#include "spi-cavium.h"
     14
     15#define DRV_NAME "spi-thunderx"
     16
     17#define SYS_FREQ_DEFAULT 700000000 /* 700 Mhz */
     18
     19static int thunderx_spi_probe(struct pci_dev *pdev,
     20			      const struct pci_device_id *ent)
     21{
     22	struct device *dev = &pdev->dev;
     23	struct spi_master *master;
     24	struct octeon_spi *p;
     25	int ret;
     26
     27	master = spi_alloc_master(dev, sizeof(struct octeon_spi));
     28	if (!master)
     29		return -ENOMEM;
     30
     31	p = spi_master_get_devdata(master);
     32
     33	ret = pcim_enable_device(pdev);
     34	if (ret)
     35		goto error;
     36
     37	ret = pci_request_regions(pdev, DRV_NAME);
     38	if (ret)
     39		goto error;
     40
     41	p->register_base = pcim_iomap(pdev, 0, pci_resource_len(pdev, 0));
     42	if (!p->register_base) {
     43		ret = -EINVAL;
     44		goto error;
     45	}
     46
     47	p->regs.config = 0x1000;
     48	p->regs.status = 0x1008;
     49	p->regs.tx = 0x1010;
     50	p->regs.data = 0x1080;
     51
     52	p->clk = devm_clk_get(dev, NULL);
     53	if (IS_ERR(p->clk)) {
     54		ret = PTR_ERR(p->clk);
     55		goto error;
     56	}
     57
     58	ret = clk_prepare_enable(p->clk);
     59	if (ret)
     60		goto error;
     61
     62	p->sys_freq = clk_get_rate(p->clk);
     63	if (!p->sys_freq)
     64		p->sys_freq = SYS_FREQ_DEFAULT;
     65	dev_info(dev, "Set system clock to %u\n", p->sys_freq);
     66
     67	master->flags = SPI_MASTER_HALF_DUPLEX;
     68	master->num_chipselect = 4;
     69	master->mode_bits = SPI_CPHA | SPI_CPOL | SPI_CS_HIGH |
     70			    SPI_LSB_FIRST | SPI_3WIRE;
     71	master->transfer_one_message = octeon_spi_transfer_one_message;
     72	master->bits_per_word_mask = SPI_BPW_MASK(8);
     73	master->max_speed_hz = OCTEON_SPI_MAX_CLOCK_HZ;
     74	master->dev.of_node = pdev->dev.of_node;
     75
     76	pci_set_drvdata(pdev, master);
     77
     78	ret = devm_spi_register_master(dev, master);
     79	if (ret)
     80		goto error;
     81
     82	return 0;
     83
     84error:
     85	clk_disable_unprepare(p->clk);
     86	pci_release_regions(pdev);
     87	spi_master_put(master);
     88	return ret;
     89}
     90
     91static void thunderx_spi_remove(struct pci_dev *pdev)
     92{
     93	struct spi_master *master = pci_get_drvdata(pdev);
     94	struct octeon_spi *p;
     95
     96	p = spi_master_get_devdata(master);
     97	if (!p)
     98		return;
     99
    100	clk_disable_unprepare(p->clk);
    101	pci_release_regions(pdev);
    102	/* Put everything in a known state. */
    103	writeq(0, p->register_base + OCTEON_SPI_CFG(p));
    104}
    105
    106static const struct pci_device_id thunderx_spi_pci_id_table[] = {
    107	{ PCI_DEVICE(PCI_VENDOR_ID_CAVIUM, 0xa00b) },
    108	{ 0, }
    109};
    110
    111MODULE_DEVICE_TABLE(pci, thunderx_spi_pci_id_table);
    112
    113static struct pci_driver thunderx_spi_driver = {
    114	.name		= DRV_NAME,
    115	.id_table	= thunderx_spi_pci_id_table,
    116	.probe		= thunderx_spi_probe,
    117	.remove		= thunderx_spi_remove,
    118};
    119
    120module_pci_driver(thunderx_spi_driver);
    121
    122MODULE_DESCRIPTION("Cavium, Inc. ThunderX SPI bus driver");
    123MODULE_AUTHOR("Jan Glauber");
    124MODULE_LICENSE("GPL");