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-altera-platform.c (4066B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Altera SPI driver
      4 *
      5 * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
      6 *
      7 * Based on spi_s3c24xx.c, which is:
      8 * Copyright (c) 2006 Ben Dooks
      9 * Copyright (c) 2006 Simtec Electronics
     10 *	Ben Dooks <ben@simtec.co.uk>
     11 */
     12
     13#include <linux/interrupt.h>
     14#include <linux/errno.h>
     15#include <linux/module.h>
     16#include <linux/platform_device.h>
     17#include <linux/spi/altera.h>
     18#include <linux/spi/spi.h>
     19#include <linux/io.h>
     20#include <linux/of.h>
     21
     22#define DRV_NAME "spi_altera"
     23
     24enum altera_spi_type {
     25	ALTERA_SPI_TYPE_UNKNOWN,
     26	ALTERA_SPI_TYPE_SUBDEV,
     27};
     28
     29static const struct regmap_config spi_altera_config = {
     30	.reg_bits = 32,
     31	.reg_stride = 4,
     32	.val_bits = 32,
     33	.fast_io = true,
     34};
     35
     36static int altera_spi_probe(struct platform_device *pdev)
     37{
     38	const struct platform_device_id *platid = platform_get_device_id(pdev);
     39	struct altera_spi_platform_data *pdata = dev_get_platdata(&pdev->dev);
     40	enum altera_spi_type type = ALTERA_SPI_TYPE_UNKNOWN;
     41	struct altera_spi *hw;
     42	struct spi_master *master;
     43	int err = -ENODEV;
     44	u16 i;
     45
     46	master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
     47	if (!master)
     48		return err;
     49
     50	/* setup the master state. */
     51	master->bus_num = -1;
     52
     53	if (pdata) {
     54		if (pdata->num_chipselect > ALTERA_SPI_MAX_CS) {
     55			dev_err(&pdev->dev,
     56				"Invalid number of chipselect: %u\n",
     57				pdata->num_chipselect);
     58			err = -EINVAL;
     59			goto exit;
     60		}
     61
     62		master->num_chipselect = pdata->num_chipselect;
     63		master->mode_bits = pdata->mode_bits;
     64		master->bits_per_word_mask = pdata->bits_per_word_mask;
     65	} else {
     66		master->num_chipselect = 16;
     67		master->mode_bits = SPI_CS_HIGH;
     68		master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 16);
     69	}
     70
     71	master->dev.of_node = pdev->dev.of_node;
     72
     73	hw = spi_master_get_devdata(master);
     74	hw->dev = &pdev->dev;
     75
     76	if (platid)
     77		type = platid->driver_data;
     78
     79	/* find and map our resources */
     80	if (type == ALTERA_SPI_TYPE_SUBDEV) {
     81		struct resource *regoff;
     82
     83		hw->regmap = dev_get_regmap(pdev->dev.parent, NULL);
     84		if (!hw->regmap) {
     85			dev_err(&pdev->dev, "get regmap failed\n");
     86			goto exit;
     87		}
     88
     89		regoff = platform_get_resource(pdev, IORESOURCE_REG, 0);
     90		if (regoff)
     91			hw->regoff = regoff->start;
     92	} else {
     93		void __iomem *res;
     94
     95		res = devm_platform_ioremap_resource(pdev, 0);
     96		if (IS_ERR(res)) {
     97			err = PTR_ERR(res);
     98			goto exit;
     99		}
    100
    101		hw->regmap = devm_regmap_init_mmio(&pdev->dev, res,
    102						   &spi_altera_config);
    103		if (IS_ERR(hw->regmap)) {
    104			dev_err(&pdev->dev, "regmap mmio init failed\n");
    105			err = PTR_ERR(hw->regmap);
    106			goto exit;
    107		}
    108	}
    109
    110	altera_spi_init_master(master);
    111
    112	/* irq is optional */
    113	hw->irq = platform_get_irq(pdev, 0);
    114	if (hw->irq >= 0) {
    115		err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
    116				       pdev->name, master);
    117		if (err)
    118			goto exit;
    119	}
    120
    121	err = devm_spi_register_master(&pdev->dev, master);
    122	if (err)
    123		goto exit;
    124
    125	if (pdata) {
    126		for (i = 0; i < pdata->num_devices; i++) {
    127			if (!spi_new_device(master, pdata->devices + i))
    128				dev_warn(&pdev->dev,
    129					 "unable to create SPI device: %s\n",
    130					 pdata->devices[i].modalias);
    131		}
    132	}
    133
    134	dev_info(&pdev->dev, "regoff %u, irq %d\n", hw->regoff, hw->irq);
    135
    136	return 0;
    137exit:
    138	spi_master_put(master);
    139	return err;
    140}
    141
    142#ifdef CONFIG_OF
    143static const struct of_device_id altera_spi_match[] = {
    144	{ .compatible = "ALTR,spi-1.0", },
    145	{ .compatible = "altr,spi-1.0", },
    146	{},
    147};
    148MODULE_DEVICE_TABLE(of, altera_spi_match);
    149#endif /* CONFIG_OF */
    150
    151static const struct platform_device_id altera_spi_ids[] = {
    152	{ DRV_NAME,		ALTERA_SPI_TYPE_UNKNOWN },
    153	{ "subdev_spi_altera",	ALTERA_SPI_TYPE_SUBDEV },
    154	{ }
    155};
    156MODULE_DEVICE_TABLE(platform, altera_spi_ids);
    157
    158static struct platform_driver altera_spi_driver = {
    159	.probe = altera_spi_probe,
    160	.driver = {
    161		.name = DRV_NAME,
    162		.pm = NULL,
    163		.of_match_table = of_match_ptr(altera_spi_match),
    164	},
    165	.id_table	= altera_spi_ids,
    166};
    167module_platform_driver(altera_spi_driver);
    168
    169MODULE_DESCRIPTION("Altera SPI driver");
    170MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
    171MODULE_LICENSE("GPL");
    172MODULE_ALIAS("platform:" DRV_NAME);