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

gen_bd.c (9425B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Driver for MPC52xx processor BestComm General Buffer Descriptor
      4 *
      5 * Copyright (C) 2007 Sylvain Munaut <tnt@246tNt.com>
      6 * Copyright (C) 2006 AppSpec Computer Technologies Corp.
      7 *                    Jeff Gibbons <jeff.gibbons@appspec.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/kernel.h>
     12#include <linux/string.h>
     13#include <linux/types.h>
     14#include <asm/errno.h>
     15#include <asm/io.h>
     16
     17#include <asm/mpc52xx.h>
     18#include <asm/mpc52xx_psc.h>
     19
     20#include <linux/fsl/bestcomm/bestcomm.h>
     21#include <linux/fsl/bestcomm/bestcomm_priv.h>
     22#include <linux/fsl/bestcomm/gen_bd.h>
     23
     24
     25/* ======================================================================== */
     26/* Task image/var/inc                                                       */
     27/* ======================================================================== */
     28
     29/* gen_bd tasks images */
     30extern u32 bcom_gen_bd_rx_task[];
     31extern u32 bcom_gen_bd_tx_task[];
     32
     33/* rx task vars that need to be set before enabling the task */
     34struct bcom_gen_bd_rx_var {
     35	u32 enable;		/* (u16*) address of task's control register */
     36	u32 fifo;		/* (u32*) address of gen_bd's fifo */
     37	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
     38	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
     39	u32 bd_start;		/* (struct bcom_bd*) current bd */
     40	u32 buffer_size;	/* size of receive buffer */
     41};
     42
     43/* rx task incs that need to be set before enabling the task */
     44struct bcom_gen_bd_rx_inc {
     45	u16 pad0;
     46	s16 incr_bytes;
     47	u16 pad1;
     48	s16 incr_dst;
     49};
     50
     51/* tx task vars that need to be set before enabling the task */
     52struct bcom_gen_bd_tx_var {
     53	u32 fifo;		/* (u32*) address of gen_bd's fifo */
     54	u32 enable;		/* (u16*) address of task's control register */
     55	u32 bd_base;		/* (struct bcom_bd*) beginning of ring buffer */
     56	u32 bd_last;		/* (struct bcom_bd*) end of ring buffer */
     57	u32 bd_start;		/* (struct bcom_bd*) current bd */
     58	u32 buffer_size;	/* set by uCode for each packet */
     59};
     60
     61/* tx task incs that need to be set before enabling the task */
     62struct bcom_gen_bd_tx_inc {
     63	u16 pad0;
     64	s16 incr_bytes;
     65	u16 pad1;
     66	s16 incr_src;
     67	u16 pad2;
     68	s16 incr_src_ma;
     69};
     70
     71/* private structure */
     72struct bcom_gen_bd_priv {
     73	phys_addr_t	fifo;
     74	int		initiator;
     75	int		ipr;
     76	int		maxbufsize;
     77};
     78
     79
     80/* ======================================================================== */
     81/* Task support code                                                        */
     82/* ======================================================================== */
     83
     84struct bcom_task *
     85bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo,
     86			int initiator, int ipr, int maxbufsize)
     87{
     88	struct bcom_task *tsk;
     89	struct bcom_gen_bd_priv *priv;
     90
     91	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
     92			sizeof(struct bcom_gen_bd_priv));
     93	if (!tsk)
     94		return NULL;
     95
     96	tsk->flags = BCOM_FLAGS_NONE;
     97
     98	priv = tsk->priv;
     99	priv->fifo	= fifo;
    100	priv->initiator	= initiator;
    101	priv->ipr	= ipr;
    102	priv->maxbufsize = maxbufsize;
    103
    104	if (bcom_gen_bd_rx_reset(tsk)) {
    105		bcom_task_free(tsk);
    106		return NULL;
    107	}
    108
    109	return tsk;
    110}
    111EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init);
    112
    113int
    114bcom_gen_bd_rx_reset(struct bcom_task *tsk)
    115{
    116	struct bcom_gen_bd_priv *priv = tsk->priv;
    117	struct bcom_gen_bd_rx_var *var;
    118	struct bcom_gen_bd_rx_inc *inc;
    119
    120	/* Shutdown the task */
    121	bcom_disable_task(tsk->tasknum);
    122
    123	/* Reset the microcode */
    124	var = (struct bcom_gen_bd_rx_var *) bcom_task_var(tsk->tasknum);
    125	inc = (struct bcom_gen_bd_rx_inc *) bcom_task_inc(tsk->tasknum);
    126
    127	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_rx_task))
    128		return -1;
    129
    130	var->enable	= bcom_eng->regs_base +
    131				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
    132	var->fifo	= (u32) priv->fifo;
    133	var->bd_base	= tsk->bd_pa;
    134	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
    135	var->bd_start	= tsk->bd_pa;
    136	var->buffer_size = priv->maxbufsize;
    137
    138	inc->incr_bytes	= -(s16)sizeof(u32);
    139	inc->incr_dst	= sizeof(u32);
    140
    141	/* Reset the BDs */
    142	tsk->index = 0;
    143	tsk->outdex = 0;
    144
    145	memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
    146
    147	/* Configure some stuff */
    148	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_RX_BD_PRAGMA);
    149	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
    150
    151	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
    152	bcom_set_initiator(tsk->tasknum, priv->initiator);
    153
    154	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
    155
    156	return 0;
    157}
    158EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_reset);
    159
    160void
    161bcom_gen_bd_rx_release(struct bcom_task *tsk)
    162{
    163	/* Nothing special for the GenBD tasks */
    164	bcom_task_free(tsk);
    165}
    166EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release);
    167
    168
    169extern struct bcom_task *
    170bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo,
    171			int initiator, int ipr)
    172{
    173	struct bcom_task *tsk;
    174	struct bcom_gen_bd_priv *priv;
    175
    176	tsk = bcom_task_alloc(queue_len, sizeof(struct bcom_gen_bd),
    177			sizeof(struct bcom_gen_bd_priv));
    178	if (!tsk)
    179		return NULL;
    180
    181	tsk->flags = BCOM_FLAGS_NONE;
    182
    183	priv = tsk->priv;
    184	priv->fifo	= fifo;
    185	priv->initiator	= initiator;
    186	priv->ipr	= ipr;
    187
    188	if (bcom_gen_bd_tx_reset(tsk)) {
    189		bcom_task_free(tsk);
    190		return NULL;
    191	}
    192
    193	return tsk;
    194}
    195EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init);
    196
    197int
    198bcom_gen_bd_tx_reset(struct bcom_task *tsk)
    199{
    200	struct bcom_gen_bd_priv *priv = tsk->priv;
    201	struct bcom_gen_bd_tx_var *var;
    202	struct bcom_gen_bd_tx_inc *inc;
    203
    204	/* Shutdown the task */
    205	bcom_disable_task(tsk->tasknum);
    206
    207	/* Reset the microcode */
    208	var = (struct bcom_gen_bd_tx_var *) bcom_task_var(tsk->tasknum);
    209	inc = (struct bcom_gen_bd_tx_inc *) bcom_task_inc(tsk->tasknum);
    210
    211	if (bcom_load_image(tsk->tasknum, bcom_gen_bd_tx_task))
    212		return -1;
    213
    214	var->enable	= bcom_eng->regs_base +
    215				offsetof(struct mpc52xx_sdma, tcr[tsk->tasknum]);
    216	var->fifo	= (u32) priv->fifo;
    217	var->bd_base	= tsk->bd_pa;
    218	var->bd_last	= tsk->bd_pa + ((tsk->num_bd-1) * tsk->bd_size);
    219	var->bd_start	= tsk->bd_pa;
    220
    221	inc->incr_bytes	= -(s16)sizeof(u32);
    222	inc->incr_src	= sizeof(u32);
    223	inc->incr_src_ma = sizeof(u8);
    224
    225	/* Reset the BDs */
    226	tsk->index = 0;
    227	tsk->outdex = 0;
    228
    229	memset_io(tsk->bd, 0x00, tsk->num_bd * tsk->bd_size);
    230
    231	/* Configure some stuff */
    232	bcom_set_task_pragma(tsk->tasknum, BCOM_GEN_TX_BD_PRAGMA);
    233	bcom_set_task_auto_start(tsk->tasknum, tsk->tasknum);
    234
    235	out_8(&bcom_eng->regs->ipr[priv->initiator], priv->ipr);
    236	bcom_set_initiator(tsk->tasknum, priv->initiator);
    237
    238	out_be32(&bcom_eng->regs->IntPend, 1<<tsk->tasknum);	/* Clear ints */
    239
    240	return 0;
    241}
    242EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_reset);
    243
    244void
    245bcom_gen_bd_tx_release(struct bcom_task *tsk)
    246{
    247	/* Nothing special for the GenBD tasks */
    248	bcom_task_free(tsk);
    249}
    250EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release);
    251
    252/* ---------------------------------------------------------------------
    253 * PSC support code
    254 */
    255
    256/**
    257 * bcom_psc_parameters - Bestcomm initialization value table for PSC devices
    258 *
    259 * This structure is only used internally.  It is a lookup table for PSC
    260 * specific parameters to bestcomm tasks.
    261 */
    262static struct bcom_psc_params {
    263	int rx_initiator;
    264	int rx_ipr;
    265	int tx_initiator;
    266	int tx_ipr;
    267} bcom_psc_params[] = {
    268	[0] = {
    269		.rx_initiator = BCOM_INITIATOR_PSC1_RX,
    270		.rx_ipr = BCOM_IPR_PSC1_RX,
    271		.tx_initiator = BCOM_INITIATOR_PSC1_TX,
    272		.tx_ipr = BCOM_IPR_PSC1_TX,
    273	},
    274	[1] = {
    275		.rx_initiator = BCOM_INITIATOR_PSC2_RX,
    276		.rx_ipr = BCOM_IPR_PSC2_RX,
    277		.tx_initiator = BCOM_INITIATOR_PSC2_TX,
    278		.tx_ipr = BCOM_IPR_PSC2_TX,
    279	},
    280	[2] = {
    281		.rx_initiator = BCOM_INITIATOR_PSC3_RX,
    282		.rx_ipr = BCOM_IPR_PSC3_RX,
    283		.tx_initiator = BCOM_INITIATOR_PSC3_TX,
    284		.tx_ipr = BCOM_IPR_PSC3_TX,
    285	},
    286	[3] = {
    287		.rx_initiator = BCOM_INITIATOR_PSC4_RX,
    288		.rx_ipr = BCOM_IPR_PSC4_RX,
    289		.tx_initiator = BCOM_INITIATOR_PSC4_TX,
    290		.tx_ipr = BCOM_IPR_PSC4_TX,
    291	},
    292	[4] = {
    293		.rx_initiator = BCOM_INITIATOR_PSC5_RX,
    294		.rx_ipr = BCOM_IPR_PSC5_RX,
    295		.tx_initiator = BCOM_INITIATOR_PSC5_TX,
    296		.tx_ipr = BCOM_IPR_PSC5_TX,
    297	},
    298	[5] = {
    299		.rx_initiator = BCOM_INITIATOR_PSC6_RX,
    300		.rx_ipr = BCOM_IPR_PSC6_RX,
    301		.tx_initiator = BCOM_INITIATOR_PSC6_TX,
    302		.tx_ipr = BCOM_IPR_PSC6_TX,
    303	},
    304};
    305
    306/**
    307 * bcom_psc_gen_bd_rx_init - Allocate a receive bcom_task for a PSC port
    308 * @psc_num:	Number of the PSC to allocate a task for
    309 * @queue_len:	number of buffer descriptors to allocate for the task
    310 * @fifo:	physical address of FIFO register
    311 * @maxbufsize:	Maximum receive data size in bytes.
    312 *
    313 * Allocate a bestcomm task structure for receiving data from a PSC.
    314 */
    315struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len,
    316					   phys_addr_t fifo, int maxbufsize)
    317{
    318	if (psc_num >= MPC52xx_PSC_MAXNUM)
    319		return NULL;
    320
    321	return bcom_gen_bd_rx_init(queue_len, fifo,
    322				   bcom_psc_params[psc_num].rx_initiator,
    323				   bcom_psc_params[psc_num].rx_ipr,
    324				   maxbufsize);
    325}
    326EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init);
    327
    328/**
    329 * bcom_psc_gen_bd_tx_init - Allocate a transmit bcom_task for a PSC port
    330 * @psc_num:	Number of the PSC to allocate a task for
    331 * @queue_len:	number of buffer descriptors to allocate for the task
    332 * @fifo:	physical address of FIFO register
    333 *
    334 * Allocate a bestcomm task structure for transmitting data to a PSC.
    335 */
    336struct bcom_task *
    337bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo)
    338{
    339	struct psc;
    340	return bcom_gen_bd_tx_init(queue_len, fifo,
    341				   bcom_psc_params[psc_num].tx_initiator,
    342				   bcom_psc_params[psc_num].tx_ipr);
    343}
    344EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_tx_init);
    345
    346
    347MODULE_DESCRIPTION("BestComm General Buffer Descriptor tasks driver");
    348MODULE_AUTHOR("Jeff Gibbons <jeff.gibbons@appspec.com>");
    349MODULE_LICENSE("GPL v2");
    350