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-dmfc.c (4948B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
      4 * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
      5 */
      6#include <linux/export.h>
      7#include <linux/types.h>
      8#include <linux/errno.h>
      9#include <linux/io.h>
     10
     11#include <video/imx-ipu-v3.h>
     12#include "ipu-prv.h"
     13
     14#define DMFC_RD_CHAN		0x0000
     15#define DMFC_WR_CHAN		0x0004
     16#define DMFC_WR_CHAN_DEF	0x0008
     17#define DMFC_DP_CHAN		0x000c
     18#define DMFC_DP_CHAN_DEF	0x0010
     19#define DMFC_GENERAL1		0x0014
     20#define DMFC_GENERAL2		0x0018
     21#define DMFC_IC_CTRL		0x001c
     22#define DMFC_WR_CHAN_ALT	0x0020
     23#define DMFC_WR_CHAN_DEF_ALT	0x0024
     24#define DMFC_DP_CHAN_ALT	0x0028
     25#define DMFC_DP_CHAN_DEF_ALT	0x002c
     26#define DMFC_GENERAL1_ALT	0x0030
     27#define DMFC_STAT		0x0034
     28
     29#define DMFC_WR_CHAN_1_28		0
     30#define DMFC_WR_CHAN_2_41		8
     31#define DMFC_WR_CHAN_1C_42		16
     32#define DMFC_WR_CHAN_2C_43		24
     33
     34#define DMFC_DP_CHAN_5B_23		0
     35#define DMFC_DP_CHAN_5F_27		8
     36#define DMFC_DP_CHAN_6B_24		16
     37#define DMFC_DP_CHAN_6F_29		24
     38
     39struct dmfc_channel_data {
     40	int		ipu_channel;
     41	unsigned long	channel_reg;
     42	unsigned long	shift;
     43	unsigned	eot_shift;
     44	unsigned	max_fifo_lines;
     45};
     46
     47static const struct dmfc_channel_data dmfcdata[] = {
     48	{
     49		.ipu_channel	= IPUV3_CHANNEL_MEM_BG_SYNC,
     50		.channel_reg	= DMFC_DP_CHAN,
     51		.shift		= DMFC_DP_CHAN_5B_23,
     52		.eot_shift	= 20,
     53		.max_fifo_lines	= 3,
     54	}, {
     55		.ipu_channel	= 24,
     56		.channel_reg	= DMFC_DP_CHAN,
     57		.shift		= DMFC_DP_CHAN_6B_24,
     58		.eot_shift	= 22,
     59		.max_fifo_lines	= 1,
     60	}, {
     61		.ipu_channel	= IPUV3_CHANNEL_MEM_FG_SYNC,
     62		.channel_reg	= DMFC_DP_CHAN,
     63		.shift		= DMFC_DP_CHAN_5F_27,
     64		.eot_shift	= 21,
     65		.max_fifo_lines	= 2,
     66	}, {
     67		.ipu_channel	= IPUV3_CHANNEL_MEM_DC_SYNC,
     68		.channel_reg	= DMFC_WR_CHAN,
     69		.shift		= DMFC_WR_CHAN_1_28,
     70		.eot_shift	= 16,
     71		.max_fifo_lines	= 2,
     72	}, {
     73		.ipu_channel	= 29,
     74		.channel_reg	= DMFC_DP_CHAN,
     75		.shift		= DMFC_DP_CHAN_6F_29,
     76		.eot_shift	= 23,
     77		.max_fifo_lines	= 1,
     78	},
     79};
     80
     81#define DMFC_NUM_CHANNELS	ARRAY_SIZE(dmfcdata)
     82
     83struct ipu_dmfc_priv;
     84
     85struct dmfc_channel {
     86	unsigned			slots;
     87	struct ipu_soc			*ipu;
     88	struct ipu_dmfc_priv		*priv;
     89	const struct dmfc_channel_data	*data;
     90};
     91
     92struct ipu_dmfc_priv {
     93	struct ipu_soc *ipu;
     94	struct device *dev;
     95	struct dmfc_channel channels[DMFC_NUM_CHANNELS];
     96	struct mutex mutex;
     97	void __iomem *base;
     98	int use_count;
     99};
    100
    101int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
    102{
    103	struct ipu_dmfc_priv *priv = dmfc->priv;
    104	mutex_lock(&priv->mutex);
    105
    106	if (!priv->use_count)
    107		ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
    108
    109	priv->use_count++;
    110
    111	mutex_unlock(&priv->mutex);
    112
    113	return 0;
    114}
    115EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
    116
    117void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
    118{
    119	struct ipu_dmfc_priv *priv = dmfc->priv;
    120
    121	mutex_lock(&priv->mutex);
    122
    123	priv->use_count--;
    124
    125	if (!priv->use_count)
    126		ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
    127
    128	if (priv->use_count < 0)
    129		priv->use_count = 0;
    130
    131	mutex_unlock(&priv->mutex);
    132}
    133EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
    134
    135void ipu_dmfc_config_wait4eot(struct dmfc_channel *dmfc, int width)
    136{
    137	struct ipu_dmfc_priv *priv = dmfc->priv;
    138	u32 dmfc_gen1;
    139
    140	mutex_lock(&priv->mutex);
    141
    142	dmfc_gen1 = readl(priv->base + DMFC_GENERAL1);
    143
    144	if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
    145		dmfc_gen1 |= 1 << dmfc->data->eot_shift;
    146	else
    147		dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
    148
    149	writel(dmfc_gen1, priv->base + DMFC_GENERAL1);
    150
    151	mutex_unlock(&priv->mutex);
    152}
    153EXPORT_SYMBOL_GPL(ipu_dmfc_config_wait4eot);
    154
    155struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
    156{
    157	struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
    158	int i;
    159
    160	for (i = 0; i < DMFC_NUM_CHANNELS; i++)
    161		if (dmfcdata[i].ipu_channel == ipu_channel)
    162			return &priv->channels[i];
    163	return ERR_PTR(-ENODEV);
    164}
    165EXPORT_SYMBOL_GPL(ipu_dmfc_get);
    166
    167void ipu_dmfc_put(struct dmfc_channel *dmfc)
    168{
    169}
    170EXPORT_SYMBOL_GPL(ipu_dmfc_put);
    171
    172int ipu_dmfc_init(struct ipu_soc *ipu, struct device *dev, unsigned long base,
    173		struct clk *ipu_clk)
    174{
    175	struct ipu_dmfc_priv *priv;
    176	int i;
    177
    178	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
    179	if (!priv)
    180		return -ENOMEM;
    181
    182	priv->base = devm_ioremap(dev, base, PAGE_SIZE);
    183	if (!priv->base)
    184		return -ENOMEM;
    185
    186	priv->dev = dev;
    187	priv->ipu = ipu;
    188	mutex_init(&priv->mutex);
    189
    190	ipu->dmfc_priv = priv;
    191
    192	for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
    193		priv->channels[i].priv = priv;
    194		priv->channels[i].ipu = ipu;
    195		priv->channels[i].data = &dmfcdata[i];
    196
    197		if (dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC ||
    198		    dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_FG_SYNC ||
    199		    dmfcdata[i].ipu_channel == IPUV3_CHANNEL_MEM_DC_SYNC)
    200			priv->channels[i].slots = 2;
    201	}
    202
    203	writel(0x00000050, priv->base + DMFC_WR_CHAN);
    204	writel(0x00005654, priv->base + DMFC_DP_CHAN);
    205	writel(0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
    206	writel(0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
    207	writel(0x00000003, priv->base + DMFC_GENERAL1);
    208
    209	return 0;
    210}
    211
    212void ipu_dmfc_exit(struct ipu_soc *ipu)
    213{
    214}