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

ipu-smfc.c (4164B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 2008-2010 Freescale Semiconductor, Inc. All Rights Reserved.
      4 */
      5#include <linux/export.h>
      6#include <linux/types.h>
      7#include <linux/init.h>
      8#include <linux/io.h>
      9#include <linux/errno.h>
     10#include <linux/spinlock.h>
     11#include <linux/delay.h>
     12#include <linux/clk.h>
     13#include <video/imx-ipu-v3.h>
     14
     15#include "ipu-prv.h"
     16
     17struct ipu_smfc {
     18	struct ipu_smfc_priv *priv;
     19	int chno;
     20	bool inuse;
     21};
     22
     23struct ipu_smfc_priv {
     24	void __iomem *base;
     25	spinlock_t lock;
     26	struct ipu_soc *ipu;
     27	struct ipu_smfc channel[4];
     28	int use_count;
     29};
     30
     31/*SMFC Registers */
     32#define SMFC_MAP	0x0000
     33#define SMFC_WMC	0x0004
     34#define SMFC_BS		0x0008
     35
     36int ipu_smfc_set_burstsize(struct ipu_smfc *smfc, int burstsize)
     37{
     38	struct ipu_smfc_priv *priv = smfc->priv;
     39	unsigned long flags;
     40	u32 val, shift;
     41
     42	spin_lock_irqsave(&priv->lock, flags);
     43
     44	shift = smfc->chno * 4;
     45	val = readl(priv->base + SMFC_BS);
     46	val &= ~(0xf << shift);
     47	val |= burstsize << shift;
     48	writel(val, priv->base + SMFC_BS);
     49
     50	spin_unlock_irqrestore(&priv->lock, flags);
     51
     52	return 0;
     53}
     54EXPORT_SYMBOL_GPL(ipu_smfc_set_burstsize);
     55
     56int ipu_smfc_map_channel(struct ipu_smfc *smfc, int csi_id, int mipi_id)
     57{
     58	struct ipu_smfc_priv *priv = smfc->priv;
     59	unsigned long flags;
     60	u32 val, shift;
     61
     62	spin_lock_irqsave(&priv->lock, flags);
     63
     64	shift = smfc->chno * 3;
     65	val = readl(priv->base + SMFC_MAP);
     66	val &= ~(0x7 << shift);
     67	val |= ((csi_id << 2) | mipi_id) << shift;
     68	writel(val, priv->base + SMFC_MAP);
     69
     70	spin_unlock_irqrestore(&priv->lock, flags);
     71
     72	return 0;
     73}
     74EXPORT_SYMBOL_GPL(ipu_smfc_map_channel);
     75
     76int ipu_smfc_set_watermark(struct ipu_smfc *smfc, u32 set_level, u32 clr_level)
     77{
     78	struct ipu_smfc_priv *priv = smfc->priv;
     79	unsigned long flags;
     80	u32 val, shift;
     81
     82	spin_lock_irqsave(&priv->lock, flags);
     83
     84	shift = smfc->chno * 6 + (smfc->chno > 1 ? 4 : 0);
     85	val = readl(priv->base + SMFC_WMC);
     86	val &= ~(0x3f << shift);
     87	val |= ((clr_level << 3) | set_level) << shift;
     88	writel(val, priv->base + SMFC_WMC);
     89
     90	spin_unlock_irqrestore(&priv->lock, flags);
     91
     92	return 0;
     93}
     94EXPORT_SYMBOL_GPL(ipu_smfc_set_watermark);
     95
     96int ipu_smfc_enable(struct ipu_smfc *smfc)
     97{
     98	struct ipu_smfc_priv *priv = smfc->priv;
     99	unsigned long flags;
    100
    101	spin_lock_irqsave(&priv->lock, flags);
    102
    103	if (!priv->use_count)
    104		ipu_module_enable(priv->ipu, IPU_CONF_SMFC_EN);
    105
    106	priv->use_count++;
    107
    108	spin_unlock_irqrestore(&priv->lock, flags);
    109
    110	return 0;
    111}
    112EXPORT_SYMBOL_GPL(ipu_smfc_enable);
    113
    114int ipu_smfc_disable(struct ipu_smfc *smfc)
    115{
    116	struct ipu_smfc_priv *priv = smfc->priv;
    117	unsigned long flags;
    118
    119	spin_lock_irqsave(&priv->lock, flags);
    120
    121	priv->use_count--;
    122
    123	if (!priv->use_count)
    124		ipu_module_disable(priv->ipu, IPU_CONF_SMFC_EN);
    125
    126	if (priv->use_count < 0)
    127		priv->use_count = 0;
    128
    129	spin_unlock_irqrestore(&priv->lock, flags);
    130
    131	return 0;
    132}
    133EXPORT_SYMBOL_GPL(ipu_smfc_disable);
    134
    135struct ipu_smfc *ipu_smfc_get(struct ipu_soc *ipu, unsigned int chno)
    136{
    137	struct ipu_smfc_priv *priv = ipu->smfc_priv;
    138	struct ipu_smfc *smfc, *ret;
    139	unsigned long flags;
    140
    141	if (chno >= 4)
    142		return ERR_PTR(-EINVAL);
    143
    144	smfc = &priv->channel[chno];
    145	ret = smfc;
    146
    147	spin_lock_irqsave(&priv->lock, flags);
    148
    149	if (smfc->inuse) {
    150		ret = ERR_PTR(-EBUSY);
    151		goto unlock;
    152	}
    153
    154	smfc->inuse = true;
    155unlock:
    156	spin_unlock_irqrestore(&priv->lock, flags);
    157	return ret;
    158}
    159EXPORT_SYMBOL_GPL(ipu_smfc_get);
    160
    161void ipu_smfc_put(struct ipu_smfc *smfc)
    162{
    163	struct ipu_smfc_priv *priv = smfc->priv;
    164	unsigned long flags;
    165
    166	spin_lock_irqsave(&priv->lock, flags);
    167	smfc->inuse = false;
    168	spin_unlock_irqrestore(&priv->lock, flags);
    169}
    170EXPORT_SYMBOL_GPL(ipu_smfc_put);
    171
    172int ipu_smfc_init(struct ipu_soc *ipu, struct device *dev,
    173		  unsigned long base)
    174{
    175	struct ipu_smfc_priv *priv;
    176	int i;
    177
    178	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    179	if (!priv)
    180		return -ENOMEM;
    181
    182	ipu->smfc_priv = priv;
    183	spin_lock_init(&priv->lock);
    184	priv->ipu = ipu;
    185
    186	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
    187	if (!priv->base)
    188		return -ENOMEM;
    189
    190	for (i = 0; i < 4; i++) {
    191		priv->channel[i].priv = priv;
    192		priv->channel[i].chno = i;
    193	}
    194
    195	pr_debug("%s: ioremap 0x%08lx -> %p\n", __func__, base, priv->base);
    196
    197	return 0;
    198}
    199
    200void ipu_smfc_exit(struct ipu_soc *ipu)
    201{
    202}