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

dma-pvr2.c (2272B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * arch/sh/drivers/dma/dma-pvr2.c
      4 *
      5 * NEC PowerVR 2 (Dreamcast) DMA support
      6 *
      7 * Copyright (C) 2003, 2004  Paul Mundt
      8 */
      9#include <linux/init.h>
     10#include <linux/kernel.h>
     11#include <linux/module.h>
     12#include <linux/interrupt.h>
     13#include <mach/sysasic.h>
     14#include <mach/dma.h>
     15#include <asm/dma.h>
     16#include <asm/io.h>
     17
     18static unsigned int xfer_complete;
     19static int count;
     20
     21static irqreturn_t pvr2_dma_interrupt(int irq, void *dev_id)
     22{
     23	if (get_dma_residue(PVR2_CASCADE_CHAN)) {
     24		printk(KERN_WARNING "DMA: SH DMAC did not complete transfer "
     25		       "on channel %d, waiting..\n", PVR2_CASCADE_CHAN);
     26		dma_wait_for_completion(PVR2_CASCADE_CHAN);
     27	}
     28
     29	if (count++ < 10)
     30		pr_debug("Got a pvr2 dma interrupt for channel %d\n",
     31			 irq - HW_EVENT_PVR2_DMA);
     32
     33	xfer_complete = 1;
     34
     35	return IRQ_HANDLED;
     36}
     37
     38static int pvr2_request_dma(struct dma_channel *chan)
     39{
     40	if (__raw_readl(PVR2_DMA_MODE) != 0)
     41		return -EBUSY;
     42
     43	__raw_writel(0, PVR2_DMA_LMMODE0);
     44
     45	return 0;
     46}
     47
     48static int pvr2_get_dma_residue(struct dma_channel *chan)
     49{
     50	return xfer_complete == 0;
     51}
     52
     53static int pvr2_xfer_dma(struct dma_channel *chan)
     54{
     55	if (chan->sar || !chan->dar)
     56		return -EINVAL;
     57
     58	xfer_complete = 0;
     59
     60	__raw_writel(chan->dar, PVR2_DMA_ADDR);
     61	__raw_writel(chan->count, PVR2_DMA_COUNT);
     62	__raw_writel(chan->mode & DMA_MODE_MASK, PVR2_DMA_MODE);
     63
     64	return 0;
     65}
     66
     67static struct dma_ops pvr2_dma_ops = {
     68	.request	= pvr2_request_dma,
     69	.get_residue	= pvr2_get_dma_residue,
     70	.xfer		= pvr2_xfer_dma,
     71};
     72
     73static struct dma_info pvr2_dma_info = {
     74	.name		= "pvr2_dmac",
     75	.nr_channels	= 1,
     76	.ops		= &pvr2_dma_ops,
     77	.flags		= DMAC_CHANNELS_TEI_CAPABLE,
     78};
     79
     80static int __init pvr2_dma_init(void)
     81{
     82	if (request_irq(HW_EVENT_PVR2_DMA, pvr2_dma_interrupt, 0,
     83			"pvr2 DMA handler", NULL))
     84		pr_err("Failed to register pvr2 DMA handler interrupt\n");
     85	request_dma(PVR2_CASCADE_CHAN, "pvr2 cascade");
     86
     87	return register_dmac(&pvr2_dma_info);
     88}
     89
     90static void __exit pvr2_dma_exit(void)
     91{
     92	free_dma(PVR2_CASCADE_CHAN);
     93	free_irq(HW_EVENT_PVR2_DMA, 0);
     94	unregister_dmac(&pvr2_dma_info);
     95}
     96
     97subsys_initcall(pvr2_dma_init);
     98module_exit(pvr2_dma_exit);
     99
    100MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
    101MODULE_DESCRIPTION("NEC PowerVR 2 DMA driver");
    102MODULE_LICENSE("GPL v2");