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-iproc-qspi.c (3914B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright 2016 Broadcom Limited
      4 */
      5
      6#include <linux/device.h>
      7#include <linux/io.h>
      8#include <linux/ioport.h>
      9#include <linux/module.h>
     10#include <linux/of.h>
     11#include <linux/of_address.h>
     12#include <linux/platform_device.h>
     13#include <linux/slab.h>
     14
     15#include "spi-bcm-qspi.h"
     16
     17#define INTR_BASE_BIT_SHIFT			0x02
     18#define INTR_COUNT				0x07
     19
     20struct bcm_iproc_intc {
     21	struct bcm_qspi_soc_intc soc_intc;
     22	struct platform_device *pdev;
     23	void __iomem *int_reg;
     24	void __iomem *int_status_reg;
     25	spinlock_t soclock;
     26	bool big_endian;
     27};
     28
     29static u32 bcm_iproc_qspi_get_l2_int_status(struct bcm_qspi_soc_intc *soc_intc)
     30{
     31	struct bcm_iproc_intc *priv =
     32			container_of(soc_intc, struct bcm_iproc_intc, soc_intc);
     33	void __iomem *mmio = priv->int_status_reg;
     34	int i;
     35	u32 val = 0, sts = 0;
     36
     37	for (i = 0; i < INTR_COUNT; i++) {
     38		if (bcm_qspi_readl(priv->big_endian, mmio + (i * 4)))
     39			val |= 1UL << i;
     40	}
     41
     42	if (val & INTR_MSPI_DONE_MASK)
     43		sts |= MSPI_DONE;
     44
     45	if (val & BSPI_LR_INTERRUPTS_ALL)
     46		sts |= BSPI_DONE;
     47
     48	if (val & BSPI_LR_INTERRUPTS_ERROR)
     49		sts |= BSPI_ERR;
     50
     51	return sts;
     52}
     53
     54static void bcm_iproc_qspi_int_ack(struct bcm_qspi_soc_intc *soc_intc, int type)
     55{
     56	struct bcm_iproc_intc *priv =
     57			container_of(soc_intc, struct bcm_iproc_intc, soc_intc);
     58	void __iomem *mmio = priv->int_status_reg;
     59	u32 mask = get_qspi_mask(type);
     60	int i;
     61
     62	for (i = 0; i < INTR_COUNT; i++) {
     63		if (mask & (1UL << i))
     64			bcm_qspi_writel(priv->big_endian, 1, mmio + (i * 4));
     65	}
     66}
     67
     68static void bcm_iproc_qspi_int_set(struct bcm_qspi_soc_intc *soc_intc, int type,
     69				   bool en)
     70{
     71	struct bcm_iproc_intc *priv =
     72			container_of(soc_intc, struct bcm_iproc_intc, soc_intc);
     73	void __iomem *mmio = priv->int_reg;
     74	u32 mask = get_qspi_mask(type);
     75	u32 val;
     76	unsigned long flags;
     77
     78	spin_lock_irqsave(&priv->soclock, flags);
     79
     80	val = bcm_qspi_readl(priv->big_endian, mmio);
     81
     82	if (en)
     83		val = val | (mask << INTR_BASE_BIT_SHIFT);
     84	else
     85		val = val & ~(mask << INTR_BASE_BIT_SHIFT);
     86
     87	bcm_qspi_writel(priv->big_endian, val, mmio);
     88
     89	spin_unlock_irqrestore(&priv->soclock, flags);
     90}
     91
     92static int bcm_iproc_probe(struct platform_device *pdev)
     93{
     94	struct device *dev = &pdev->dev;
     95	struct bcm_iproc_intc *priv;
     96	struct bcm_qspi_soc_intc *soc_intc;
     97	struct resource *res;
     98
     99	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    100	if (!priv)
    101		return -ENOMEM;
    102	soc_intc = &priv->soc_intc;
    103	priv->pdev = pdev;
    104
    105	spin_lock_init(&priv->soclock);
    106
    107	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "intr_regs");
    108	priv->int_reg = devm_ioremap_resource(dev, res);
    109	if (IS_ERR(priv->int_reg))
    110		return PTR_ERR(priv->int_reg);
    111
    112	res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
    113					   "intr_status_reg");
    114	priv->int_status_reg = devm_ioremap_resource(dev, res);
    115	if (IS_ERR(priv->int_status_reg))
    116		return PTR_ERR(priv->int_status_reg);
    117
    118	priv->big_endian = of_device_is_big_endian(dev->of_node);
    119
    120	bcm_iproc_qspi_int_ack(soc_intc, MSPI_BSPI_DONE);
    121	bcm_iproc_qspi_int_set(soc_intc, MSPI_BSPI_DONE, false);
    122
    123	soc_intc->bcm_qspi_int_ack = bcm_iproc_qspi_int_ack;
    124	soc_intc->bcm_qspi_int_set = bcm_iproc_qspi_int_set;
    125	soc_intc->bcm_qspi_get_int_status = bcm_iproc_qspi_get_l2_int_status;
    126
    127	return bcm_qspi_probe(pdev, soc_intc);
    128}
    129
    130static int bcm_iproc_remove(struct platform_device *pdev)
    131{
    132	return bcm_qspi_remove(pdev);
    133}
    134
    135static const struct of_device_id bcm_iproc_of_match[] = {
    136	{ .compatible = "brcm,spi-nsp-qspi" },
    137	{ .compatible = "brcm,spi-ns2-qspi" },
    138	{},
    139};
    140MODULE_DEVICE_TABLE(of, bcm_iproc_of_match);
    141
    142static struct platform_driver bcm_iproc_driver = {
    143	.probe			= bcm_iproc_probe,
    144	.remove			= bcm_iproc_remove,
    145	.driver = {
    146		.name		= "bcm_iproc",
    147		.pm		= &bcm_qspi_pm_ops,
    148		.of_match_table = bcm_iproc_of_match,
    149	}
    150};
    151module_platform_driver(bcm_iproc_driver);
    152
    153MODULE_LICENSE("GPL v2");
    154MODULE_AUTHOR("Kamal Dasu");
    155MODULE_DESCRIPTION("SPI flash driver for Broadcom iProc SoCs");