None of these files are actually using any __init type directives and hence don't need to include <linux/init.h>. Most are just a left over from __devinit and __cpuinit removal, or simply due to code getting copied from one driver to the next. Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
		
			
				
	
	
		
			256 lines
		
	
	
	
		
			5.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			256 lines
		
	
	
	
		
			5.8 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
/* ebus.c: EBUS DMA library code.
 | 
						|
 *
 | 
						|
 * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
 | 
						|
 * Copyright (C) 1999  David S. Miller (davem@redhat.com)
 | 
						|
 */
 | 
						|
 | 
						|
#include <linux/export.h>
 | 
						|
#include <linux/kernel.h>
 | 
						|
#include <linux/types.h>
 | 
						|
#include <linux/interrupt.h>
 | 
						|
#include <linux/delay.h>
 | 
						|
 | 
						|
#include <asm/ebus_dma.h>
 | 
						|
#include <asm/io.h>
 | 
						|
 | 
						|
#define EBDMA_CSR	0x00UL	/* Control/Status */
 | 
						|
#define EBDMA_ADDR	0x04UL	/* DMA Address */
 | 
						|
#define EBDMA_COUNT	0x08UL	/* DMA Count */
 | 
						|
 | 
						|
#define EBDMA_CSR_INT_PEND	0x00000001
 | 
						|
#define EBDMA_CSR_ERR_PEND	0x00000002
 | 
						|
#define EBDMA_CSR_DRAIN		0x00000004
 | 
						|
#define EBDMA_CSR_INT_EN	0x00000010
 | 
						|
#define EBDMA_CSR_RESET		0x00000080
 | 
						|
#define EBDMA_CSR_WRITE		0x00000100
 | 
						|
#define EBDMA_CSR_EN_DMA	0x00000200
 | 
						|
#define EBDMA_CSR_CYC_PEND	0x00000400
 | 
						|
#define EBDMA_CSR_DIAG_RD_DONE	0x00000800
 | 
						|
#define EBDMA_CSR_DIAG_WR_DONE	0x00001000
 | 
						|
#define EBDMA_CSR_EN_CNT	0x00002000
 | 
						|
#define EBDMA_CSR_TC		0x00004000
 | 
						|
#define EBDMA_CSR_DIS_CSR_DRN	0x00010000
 | 
						|
#define EBDMA_CSR_BURST_SZ_MASK	0x000c0000
 | 
						|
#define EBDMA_CSR_BURST_SZ_1	0x00080000
 | 
						|
#define EBDMA_CSR_BURST_SZ_4	0x00000000
 | 
						|
#define EBDMA_CSR_BURST_SZ_8	0x00040000
 | 
						|
#define EBDMA_CSR_BURST_SZ_16	0x000c0000
 | 
						|
#define EBDMA_CSR_DIAG_EN	0x00100000
 | 
						|
#define EBDMA_CSR_DIS_ERR_PEND	0x00400000
 | 
						|
#define EBDMA_CSR_TCI_DIS	0x00800000
 | 
						|
#define EBDMA_CSR_EN_NEXT	0x01000000
 | 
						|
#define EBDMA_CSR_DMA_ON	0x02000000
 | 
						|
#define EBDMA_CSR_A_LOADED	0x04000000
 | 
						|
#define EBDMA_CSR_NA_LOADED	0x08000000
 | 
						|
#define EBDMA_CSR_DEV_ID_MASK	0xf0000000
 | 
						|
 | 
						|
#define EBUS_DMA_RESET_TIMEOUT	10000
 | 
						|
 | 
						|
static void __ebus_dma_reset(struct ebus_dma_info *p, int no_drain)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	u32 val = 0;
 | 
						|
 | 
						|
	writel(EBDMA_CSR_RESET, p->regs + EBDMA_CSR);
 | 
						|
	udelay(1);
 | 
						|
 | 
						|
	if (no_drain)
 | 
						|
		return;
 | 
						|
 | 
						|
	for (i = EBUS_DMA_RESET_TIMEOUT; i > 0; i--) {
 | 
						|
		val = readl(p->regs + EBDMA_CSR);
 | 
						|
 | 
						|
		if (!(val & (EBDMA_CSR_DRAIN | EBDMA_CSR_CYC_PEND)))
 | 
						|
			break;
 | 
						|
		udelay(10);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static irqreturn_t ebus_dma_irq(int irq, void *dev_id)
 | 
						|
{
 | 
						|
	struct ebus_dma_info *p = dev_id;
 | 
						|
	unsigned long flags;
 | 
						|
	u32 csr = 0;
 | 
						|
 | 
						|
	spin_lock_irqsave(&p->lock, flags);
 | 
						|
	csr = readl(p->regs + EBDMA_CSR);
 | 
						|
	writel(csr, p->regs + EBDMA_CSR);
 | 
						|
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
 | 
						|
	if (csr & EBDMA_CSR_ERR_PEND) {
 | 
						|
		printk(KERN_CRIT "ebus_dma(%s): DMA error!\n", p->name);
 | 
						|
		p->callback(p, EBUS_DMA_EVENT_ERROR, p->client_cookie);
 | 
						|
		return IRQ_HANDLED;
 | 
						|
	} else if (csr & EBDMA_CSR_INT_PEND) {
 | 
						|
		p->callback(p,
 | 
						|
			    (csr & EBDMA_CSR_TC) ?
 | 
						|
			    EBUS_DMA_EVENT_DMA : EBUS_DMA_EVENT_DEVICE,
 | 
						|
			    p->client_cookie);
 | 
						|
		return IRQ_HANDLED;
 | 
						|
	}
 | 
						|
 | 
						|
	return IRQ_NONE;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
int ebus_dma_register(struct ebus_dma_info *p)
 | 
						|
{
 | 
						|
	u32 csr;
 | 
						|
 | 
						|
	if (!p->regs)
 | 
						|
		return -EINVAL;
 | 
						|
	if (p->flags & ~(EBUS_DMA_FLAG_USE_EBDMA_HANDLER |
 | 
						|
			 EBUS_DMA_FLAG_TCI_DISABLE))
 | 
						|
		return -EINVAL;
 | 
						|
	if ((p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) && !p->callback)
 | 
						|
		return -EINVAL;
 | 
						|
	if (!strlen(p->name))
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	__ebus_dma_reset(p, 1);
 | 
						|
 | 
						|
	csr = EBDMA_CSR_BURST_SZ_16 | EBDMA_CSR_EN_CNT;
 | 
						|
 | 
						|
	if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE)
 | 
						|
		csr |= EBDMA_CSR_TCI_DIS;
 | 
						|
 | 
						|
	writel(csr, p->regs + EBDMA_CSR);
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_register);
 | 
						|
 | 
						|
int ebus_dma_irq_enable(struct ebus_dma_info *p, int on)
 | 
						|
{
 | 
						|
	unsigned long flags;
 | 
						|
	u32 csr;
 | 
						|
 | 
						|
	if (on) {
 | 
						|
		if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) {
 | 
						|
			if (request_irq(p->irq, ebus_dma_irq, IRQF_SHARED, p->name, p))
 | 
						|
				return -EBUSY;
 | 
						|
		}
 | 
						|
 | 
						|
		spin_lock_irqsave(&p->lock, flags);
 | 
						|
		csr = readl(p->regs + EBDMA_CSR);
 | 
						|
		csr |= EBDMA_CSR_INT_EN;
 | 
						|
		writel(csr, p->regs + EBDMA_CSR);
 | 
						|
		spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
	} else {
 | 
						|
		spin_lock_irqsave(&p->lock, flags);
 | 
						|
		csr = readl(p->regs + EBDMA_CSR);
 | 
						|
		csr &= ~EBDMA_CSR_INT_EN;
 | 
						|
		writel(csr, p->regs + EBDMA_CSR);
 | 
						|
		spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
 | 
						|
		if (p->flags & EBUS_DMA_FLAG_USE_EBDMA_HANDLER) {
 | 
						|
			free_irq(p->irq, p);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_irq_enable);
 | 
						|
 | 
						|
void ebus_dma_unregister(struct ebus_dma_info *p)
 | 
						|
{
 | 
						|
	unsigned long flags;
 | 
						|
	u32 csr;
 | 
						|
	int irq_on = 0;
 | 
						|
 | 
						|
	spin_lock_irqsave(&p->lock, flags);
 | 
						|
	csr = readl(p->regs + EBDMA_CSR);
 | 
						|
	if (csr & EBDMA_CSR_INT_EN) {
 | 
						|
		csr &= ~EBDMA_CSR_INT_EN;
 | 
						|
		writel(csr, p->regs + EBDMA_CSR);
 | 
						|
		irq_on = 1;
 | 
						|
	}
 | 
						|
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
 | 
						|
	if (irq_on)
 | 
						|
		free_irq(p->irq, p);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_unregister);
 | 
						|
 | 
						|
int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, size_t len)
 | 
						|
{
 | 
						|
	unsigned long flags;
 | 
						|
	u32 csr;
 | 
						|
	int err;
 | 
						|
 | 
						|
	if (len >= (1 << 24))
 | 
						|
		return -EINVAL;
 | 
						|
 | 
						|
	spin_lock_irqsave(&p->lock, flags);
 | 
						|
	csr = readl(p->regs + EBDMA_CSR);
 | 
						|
	err = -EINVAL;
 | 
						|
	if (!(csr & EBDMA_CSR_EN_DMA))
 | 
						|
		goto out;
 | 
						|
	err = -EBUSY;
 | 
						|
	if (csr & EBDMA_CSR_NA_LOADED)
 | 
						|
		goto out;
 | 
						|
 | 
						|
	writel(len,      p->regs + EBDMA_COUNT);
 | 
						|
	writel(bus_addr, p->regs + EBDMA_ADDR);
 | 
						|
	err = 0;
 | 
						|
 | 
						|
out:
 | 
						|
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
 | 
						|
	return err;
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_request);
 | 
						|
 | 
						|
void ebus_dma_prepare(struct ebus_dma_info *p, int write)
 | 
						|
{
 | 
						|
	unsigned long flags;
 | 
						|
	u32 csr;
 | 
						|
 | 
						|
	spin_lock_irqsave(&p->lock, flags);
 | 
						|
	__ebus_dma_reset(p, 0);
 | 
						|
 | 
						|
	csr = (EBDMA_CSR_INT_EN |
 | 
						|
	       EBDMA_CSR_EN_CNT |
 | 
						|
	       EBDMA_CSR_BURST_SZ_16 |
 | 
						|
	       EBDMA_CSR_EN_NEXT);
 | 
						|
 | 
						|
	if (write)
 | 
						|
		csr |= EBDMA_CSR_WRITE;
 | 
						|
	if (p->flags & EBUS_DMA_FLAG_TCI_DISABLE)
 | 
						|
		csr |= EBDMA_CSR_TCI_DIS;
 | 
						|
 | 
						|
	writel(csr, p->regs + EBDMA_CSR);
 | 
						|
 | 
						|
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_prepare);
 | 
						|
 | 
						|
unsigned int ebus_dma_residue(struct ebus_dma_info *p)
 | 
						|
{
 | 
						|
	return readl(p->regs + EBDMA_COUNT);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_residue);
 | 
						|
 | 
						|
unsigned int ebus_dma_addr(struct ebus_dma_info *p)
 | 
						|
{
 | 
						|
	return readl(p->regs + EBDMA_ADDR);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_addr);
 | 
						|
 | 
						|
void ebus_dma_enable(struct ebus_dma_info *p, int on)
 | 
						|
{
 | 
						|
	unsigned long flags;
 | 
						|
	u32 orig_csr, csr;
 | 
						|
 | 
						|
	spin_lock_irqsave(&p->lock, flags);
 | 
						|
	orig_csr = csr = readl(p->regs + EBDMA_CSR);
 | 
						|
	if (on)
 | 
						|
		csr |= EBDMA_CSR_EN_DMA;
 | 
						|
	else
 | 
						|
		csr &= ~EBDMA_CSR_EN_DMA;
 | 
						|
	if ((orig_csr & EBDMA_CSR_EN_DMA) !=
 | 
						|
	    (csr & EBDMA_CSR_EN_DMA))
 | 
						|
		writel(csr, p->regs + EBDMA_CSR);
 | 
						|
	spin_unlock_irqrestore(&p->lock, flags);
 | 
						|
}
 | 
						|
EXPORT_SYMBOL(ebus_dma_enable);
 |