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

flexcop-dma.c (4399B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
      4 * flexcop-dma.c - configuring and controlling the DMA of the FlexCop
      5 * see flexcop.c for copyright information
      6 */
      7#include "flexcop.h"
      8
      9int flexcop_dma_allocate(struct pci_dev *pdev,
     10		struct flexcop_dma *dma, u32 size)
     11{
     12	u8 *tcpu;
     13	dma_addr_t tdma = 0;
     14
     15	if (size % 2) {
     16		err("dma buffersize has to be even.");
     17		return -EINVAL;
     18	}
     19
     20	tcpu = dma_alloc_coherent(&pdev->dev, size, &tdma, GFP_KERNEL);
     21	if (tcpu != NULL) {
     22		dma->pdev = pdev;
     23		dma->cpu_addr0 = tcpu;
     24		dma->dma_addr0 = tdma;
     25		dma->cpu_addr1 = tcpu + size/2;
     26		dma->dma_addr1 = tdma + size/2;
     27		dma->size = size/2;
     28		return 0;
     29	}
     30	return -ENOMEM;
     31}
     32EXPORT_SYMBOL(flexcop_dma_allocate);
     33
     34void flexcop_dma_free(struct flexcop_dma *dma)
     35{
     36	dma_free_coherent(&dma->pdev->dev, dma->size * 2, dma->cpu_addr0,
     37			  dma->dma_addr0);
     38	memset(dma, 0, sizeof(struct flexcop_dma));
     39}
     40EXPORT_SYMBOL(flexcop_dma_free);
     41
     42int flexcop_dma_config(struct flexcop_device *fc,
     43		struct flexcop_dma *dma,
     44		flexcop_dma_index_t dma_idx)
     45{
     46	flexcop_ibi_value v0x0, v0x4, v0xc;
     47
     48	v0x0.raw = v0x4.raw = v0xc.raw = 0;
     49	v0x0.dma_0x0.dma_address0 = dma->dma_addr0 >> 2;
     50	v0xc.dma_0xc.dma_address1 = dma->dma_addr1 >> 2;
     51	v0x4.dma_0x4_write.dma_addr_size = dma->size / 4;
     52
     53	if ((dma_idx & FC_DMA_1) == dma_idx) {
     54		fc->write_ibi_reg(fc, dma1_000, v0x0);
     55		fc->write_ibi_reg(fc, dma1_004, v0x4);
     56		fc->write_ibi_reg(fc, dma1_00c, v0xc);
     57	} else if ((dma_idx & FC_DMA_2) == dma_idx) {
     58		fc->write_ibi_reg(fc, dma2_010, v0x0);
     59		fc->write_ibi_reg(fc, dma2_014, v0x4);
     60		fc->write_ibi_reg(fc, dma2_01c, v0xc);
     61	} else {
     62		err("either DMA1 or DMA2 can be configured within one %s call.",
     63			__func__);
     64		return -EINVAL;
     65	}
     66
     67	return 0;
     68}
     69EXPORT_SYMBOL(flexcop_dma_config);
     70
     71/* start the DMA transfers, but not the DMA IRQs */
     72int flexcop_dma_xfer_control(struct flexcop_device *fc,
     73		flexcop_dma_index_t dma_idx,
     74		flexcop_dma_addr_index_t index,
     75		int onoff)
     76{
     77	flexcop_ibi_value v0x0, v0xc;
     78	flexcop_ibi_register r0x0, r0xc;
     79
     80	if ((dma_idx & FC_DMA_1) == dma_idx) {
     81		r0x0 = dma1_000;
     82		r0xc = dma1_00c;
     83	} else if ((dma_idx & FC_DMA_2) == dma_idx) {
     84		r0x0 = dma2_010;
     85		r0xc = dma2_01c;
     86	} else {
     87		err("transfer DMA1 or DMA2 can be started within one %s call.",
     88			__func__);
     89		return -EINVAL;
     90	}
     91
     92	v0x0 = fc->read_ibi_reg(fc, r0x0);
     93	v0xc = fc->read_ibi_reg(fc, r0xc);
     94
     95	deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw);
     96	deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw);
     97
     98	if (index & FC_DMA_SUBADDR_0)
     99		v0x0.dma_0x0.dma_0start = onoff;
    100
    101	if (index & FC_DMA_SUBADDR_1)
    102		v0xc.dma_0xc.dma_1start = onoff;
    103
    104	fc->write_ibi_reg(fc, r0x0, v0x0);
    105	fc->write_ibi_reg(fc, r0xc, v0xc);
    106
    107	deb_rdump("reg: %03x: %x\n", r0x0, v0x0.raw);
    108	deb_rdump("reg: %03x: %x\n", r0xc, v0xc.raw);
    109	return 0;
    110}
    111EXPORT_SYMBOL(flexcop_dma_xfer_control);
    112
    113static int flexcop_dma_remap(struct flexcop_device *fc,
    114		flexcop_dma_index_t dma_idx,
    115		int onoff)
    116{
    117	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_00c : dma2_01c;
    118	flexcop_ibi_value v = fc->read_ibi_reg(fc, r);
    119
    120	deb_info("%s\n", __func__);
    121	v.dma_0xc.remap_enable = onoff;
    122	fc->write_ibi_reg(fc, r, v);
    123	return 0;
    124}
    125
    126int flexcop_dma_control_size_irq(struct flexcop_device *fc,
    127		flexcop_dma_index_t no,
    128		int onoff)
    129{
    130	flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
    131
    132	if (no & FC_DMA_1)
    133		v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
    134
    135	if (no & FC_DMA_2)
    136		v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
    137
    138	fc->write_ibi_reg(fc, ctrl_208, v);
    139	return 0;
    140}
    141EXPORT_SYMBOL(flexcop_dma_control_size_irq);
    142
    143int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
    144		flexcop_dma_index_t no,
    145		int onoff)
    146{
    147	flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
    148
    149	if (no & FC_DMA_1)
    150		v.ctrl_208.DMA1_Timer_Enable_sig = onoff;
    151
    152	if (no & FC_DMA_2)
    153		v.ctrl_208.DMA2_Timer_Enable_sig = onoff;
    154
    155	fc->write_ibi_reg(fc, ctrl_208, v);
    156	return 0;
    157}
    158EXPORT_SYMBOL(flexcop_dma_control_timer_irq);
    159
    160/* 1 cycles = 1.97 msec */
    161int flexcop_dma_config_timer(struct flexcop_device *fc,
    162		flexcop_dma_index_t dma_idx, u8 cycles)
    163{
    164	flexcop_ibi_register r = (dma_idx & FC_DMA_1) ? dma1_004 : dma2_014;
    165	flexcop_ibi_value v = fc->read_ibi_reg(fc, r);
    166
    167	flexcop_dma_remap(fc, dma_idx, 0);
    168
    169	deb_info("%s\n", __func__);
    170	v.dma_0x4_write.dmatimer = cycles;
    171	fc->write_ibi_reg(fc, r, v);
    172	return 0;
    173}
    174EXPORT_SYMBOL(flexcop_dma_config_timer);
    175