예제 #1
0
파일: dbdma.c 프로젝트: 0x7f454c46/linux
static irqreturn_t dbdma_interrupt(int irq, void *dev_id)
{
	u32 intstat;
	u32 chan_index;
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;
	au1x_dma_chan_t *cp;

	intstat = dbdma_gptr->ddma_intstat;
	wmb(); /* drain writebuffer */
	chan_index = __ffs(intstat);

	ctp = chan_tab_ptr[chan_index];
	cp = ctp->chan_ptr;
	dp = ctp->cur_ptr;

	/* Reset interrupt. */
	cp->ddma_irq = 0;
	wmb(); /* drain writebuffer */

	if (ctp->chan_callback)
		ctp->chan_callback(irq, ctp->chan_callparam);

	ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
	return IRQ_RETVAL(1);
}
예제 #2
0
파일: dbdma.c 프로젝트: 1x23/unifi-gpl
static irqreturn_t
dbdma_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	u32 intstat;
	u32 chan_index;
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;
	au1x_dma_chan_t *cp;

	intstat = dbdma_gptr->ddma_intstat;
	au_sync();
	chan_index = au_ffs(intstat) - 1;

	ctp = chan_tab_ptr[chan_index];
	cp = ctp->chan_ptr;
	dp = ctp->cur_ptr;

	/* Reset interrupt.
	*/
	cp->ddma_irq = 0;
	au_sync();

	if (ctp->chan_callback)
		(ctp->chan_callback)(irq, ctp->chan_callparam, regs);

	ctp->cur_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
	return IRQ_RETVAL(1);
}
예제 #3
0
파일: dbdma.c 프로젝트: 1x23/unifi-gpl
void
au1xxx_dbdma_reset(u32 chanid)
{
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;

	au1xxx_dbdma_stop(chanid);

	ctp = *((chan_tab_t **)chanid);
	ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;

	/* Run through the descriptors and reset the valid indicator.
	*/
	dp = ctp->chan_desc_base;

	do {
		dp->dscr_cmd0 &= ~DSCR_CMD0_V;
		/* reset our SW status -- this is used to determine
		 * if a descriptor is in use by upper level SW. Since
		 * posting can reset 'V' bit.
		 */
		dp->sw_status = 0;
		dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
	} while (dp != ctp->chan_desc_base);
}
예제 #4
0
파일: dbdma.c 프로젝트: 1x23/unifi-gpl
/* Put a destination buffer into the DMA ring.
 * This updates the destination pointer and byte count.  Normally used
 * to place an empty buffer into the ring for fifo to memory transfers.
 */
u32
_au1xxx_dbdma_put_dest(u32 chanid, void *buf, int nbytes, u32 flags)
{
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;

	/* I guess we could check this to be within the
	 * range of the table......
	 */
	ctp = *((chan_tab_t **)chanid);

	/* We should have multiple callers for a particular channel,
	 * an interrupt doesn't affect this pointer nor the descriptor,
	 * so no locking should be needed.
	 */
	dp = ctp->put_ptr;

	/* If the descriptor is valid, we are way ahead of the DMA
	 * engine, so just return an error condition.
	 */
	if (dp->dscr_cmd0 & DSCR_CMD0_V)
		return 0;

	/* Load up buffer address and byte count */

	/* Check flags  */
	if (flags & DDMA_FLAGS_IE)
		dp->dscr_cmd0 |= DSCR_CMD0_IE;
	if (flags & DDMA_FLAGS_NOIE)
		dp->dscr_cmd0 &= ~DSCR_CMD0_IE;

	dp->dscr_dest0 = virt_to_phys(buf);
	dp->dscr_cmd1 = nbytes;
#if 0
	printk("cmd0:%x cmd1:%x source0:%x source1:%x dest0:%x dest1:%x\n",
			dp->dscr_cmd0, dp->dscr_cmd1, dp->dscr_source0,
			dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1 );
#endif
	/*
	 * There is an errata on the Au1200/Au1550 parts that could result in
	 * "stale" data being DMA'd. It has to do with the snoop logic on the
	 * dache eviction buffer. NONCOHERENT_IO is on by default for these
	 * parts. If it is fixedin the future, these dma_cache_inv will just
	 * be nothing more than empty macros. See io.h.
	 * */
	dma_cache_inv((unsigned long)buf,nbytes);
	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
	au_sync();
	dma_cache_wback_inv((unsigned long)dp, sizeof(dp));
        ctp->chan_ptr->ddma_dbell = 0;

	/* Get next descriptor pointer.
	*/
	ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));

	/* return something not zero.
	*/
	return nbytes;
}
예제 #5
0
파일: dbdma.c 프로젝트: 0x7f454c46/linux
/*
 * Put a source buffer into the DMA ring.
 * This updates the source pointer and byte count.  Normally used
 * for memory to fifo transfers.
 */
u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags)
{
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;

	/*
	 * I guess we could check this to be within the
	 * range of the table......
	 */
	ctp = *(chan_tab_t **)chanid;

	/*
	 * We should have multiple callers for a particular channel,
	 * an interrupt doesn't affect this pointer nor the descriptor,
	 * so no locking should be needed.
	 */
	dp = ctp->put_ptr;

	/*
	 * If the descriptor is valid, we are way ahead of the DMA
	 * engine, so just return an error condition.
	 */
	if (dp->dscr_cmd0 & DSCR_CMD0_V)
		return 0;

	/* Load up buffer address and byte count. */
	dp->dscr_source0 = buf & ~0UL;
	dp->dscr_cmd1 = nbytes;
	/* Check flags */
	if (flags & DDMA_FLAGS_IE)
		dp->dscr_cmd0 |= DSCR_CMD0_IE;
	if (flags & DDMA_FLAGS_NOIE)
		dp->dscr_cmd0 &= ~DSCR_CMD0_IE;

	/*
	 * There is an errata on the Au1200/Au1550 parts that could result
	 * in "stale" data being DMA'ed. It has to do with the snoop logic on
	 * the cache eviction buffer.  DMA_NONCOHERENT is on by default for
	 * these parts. If it is fixed in the future, these dma_cache_inv will
	 * just be nothing more than empty macros. See io.h.
	 */
	dma_cache_wback_inv((unsigned long)buf, nbytes);
	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
	wmb(); /* drain writebuffer */
	dma_cache_wback_inv((unsigned long)dp, sizeof(*dp));
	ctp->chan_ptr->ddma_dbell = 0;

	/* Get next descriptor pointer. */
	ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));

	/* Return something non-zero. */
	return nbytes;
}
예제 #6
0
파일: dbdma.c 프로젝트: 1x23/unifi-gpl
/* Put a descriptor into the DMA ring.
 * This updates the source/destination pointers and byte count.
 */
u32
au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr )
{
	chan_tab_t *ctp;
	au1x_ddma_desc_t *dp;
	u32 nbytes=0;

	/* I guess we could check this to be within the
	* range of the table......
	*/
	ctp = *((chan_tab_t **)chanid);

	/* We should have multiple callers for a particular channel,
	* an interrupt doesn't affect this pointer nor the descriptor,
	* so no locking should be needed.
	*/
	dp = ctp->put_ptr;

	/* If the descriptor is valid, we are way ahead of the DMA
	* engine, so just return an error condition.
	*/
	if (dp->dscr_cmd0 & DSCR_CMD0_V)
		return 0;

	/* Load up buffer addresses and byte count.
	*/
	dp->dscr_dest0 = dscr->dscr_dest0;
	dp->dscr_source0 = dscr->dscr_source0;
	dp->dscr_dest1 = dscr->dscr_dest1;
	dp->dscr_source1 = dscr->dscr_source1;
	dp->dscr_cmd1 = dscr->dscr_cmd1;
	nbytes = dscr->dscr_cmd1;
	/* Allow the caller to specifiy if an interrupt is generated */
	dp->dscr_cmd0 &= ~DSCR_CMD0_IE;
	dp->dscr_cmd0 |= dscr->dscr_cmd0 | DSCR_CMD0_V;
	ctp->chan_ptr->ddma_dbell = 0;

	/* Get next descriptor pointer.
	*/
	ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));

	/* return something not zero.
	*/
	return nbytes;
}
예제 #7
0
void
au1xxx_dbdma_reset(u32 chanid)
{
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;

	au1xxx_dbdma_stop(chanid);

	ctp = *((chan_tab_t **)chanid);
	ctp->get_ptr = ctp->put_ptr = ctp->cur_ptr = ctp->chan_desc_base;

	/* Run through the descriptors and reset the valid indicator.
	*/
	dp = ctp->chan_desc_base;

	do {
		dp->dscr_cmd0 &= ~DSCR_CMD0_V;
		dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
	} while (dp != ctp->chan_desc_base);
}
예제 #8
0
파일: dbdma.c 프로젝트: 0x7f454c46/linux
void au1xxx_dbdma_dump(u32 chanid)
{
	chan_tab_t	 *ctp;
	au1x_ddma_desc_t *dp;
	dbdev_tab_t	 *stp, *dtp;
	au1x_dma_chan_t	 *cp;
	u32 i		 = 0;

	ctp = *((chan_tab_t **)chanid);
	stp = ctp->chan_src;
	dtp = ctp->chan_dest;
	cp = ctp->chan_ptr;

	printk(KERN_DEBUG "Chan %x, stp %x (dev %d)  dtp %x (dev %d)\n",
			  (u32)ctp, (u32)stp, stp - dbdev_tab, (u32)dtp,
			  dtp - dbdev_tab);
	printk(KERN_DEBUG "desc base %x, get %x, put %x, cur %x\n",
			  (u32)(ctp->chan_desc_base), (u32)(ctp->get_ptr),
			  (u32)(ctp->put_ptr), (u32)(ctp->cur_ptr));

	printk(KERN_DEBUG "dbdma chan %x\n", (u32)cp);
	printk(KERN_DEBUG "cfg %08x, desptr %08x, statptr %08x\n",
			  cp->ddma_cfg, cp->ddma_desptr, cp->ddma_statptr);
	printk(KERN_DEBUG "dbell %08x, irq %08x, stat %08x, bytecnt %08x\n",
			  cp->ddma_dbell, cp->ddma_irq, cp->ddma_stat,
			  cp->ddma_bytecnt);

	/* Run through the descriptors */
	dp = ctp->chan_desc_base;

	do {
		printk(KERN_DEBUG "Dp[%d]= %08x, cmd0 %08x, cmd1 %08x\n",
				  i++, (u32)dp, dp->dscr_cmd0, dp->dscr_cmd1);
		printk(KERN_DEBUG "src0 %08x, src1 %08x, dest0 %08x, dest1 %08x\n",
				  dp->dscr_source0, dp->dscr_source1,
				  dp->dscr_dest0, dp->dscr_dest1);
		printk(KERN_DEBUG "stat %08x, nxtptr %08x\n",
				  dp->dscr_stat, dp->dscr_nxtptr);
		dp = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
	} while (dp != ctp->chan_desc_base);
}
예제 #9
0
/* Put a source buffer into the DMA ring.
 * This updates the source pointer and byte count.  Normally used
 * for memory to fifo transfers.
 */
u32
au1xxx_dbdma_put_source(u32 chanid, void *buf, int nbytes)
{
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;

	/* I guess we could check this to be within the
	 * range of the table......
	 */
	ctp = *((chan_tab_t **)chanid);

	/* We should have multiple callers for a particular channel,
	 * an interrupt doesn't affect this pointer nor the descriptor,
	 * so no locking should be needed.
	 */
	dp = ctp->put_ptr;

	/* If the descriptor is valid, we are way ahead of the DMA
	 * engine, so just return an error condition.
	 */
	if (dp->dscr_cmd0 & DSCR_CMD0_V) {
		return 0;
	}
	
	/* Load up buffer address and byte count.
	*/
	dp->dscr_source0 = virt_to_phys(buf);
	dp->dscr_cmd1 = nbytes;
	dp->dscr_cmd0 |= DSCR_CMD0_V;	/* Let it rip */
	ctp->chan_ptr->ddma_dbell = 0xffffffff;	/* Make it go */
	
	/* Get next descriptor pointer.
	*/
	ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));

	/* return something not zero.
	*/
	return nbytes;
}
예제 #10
0
파일: dbdma.c 프로젝트: 1x23/unifi-gpl
/* Get a destination buffer into the DMA ring.
 * Normally used to get a full buffer from the ring during fifo
 * to memory transfers.  This does not set the valid bit, you will
 * have to put another destination buffer to keep the DMA going.
 */
u32
au1xxx_dbdma_get_dest(u32 chanid, void **buf, int *nbytes)
{
	chan_tab_t		*ctp;
	au1x_ddma_desc_t	*dp;
	u32			rv;

	/* I guess we could check this to be within the
	 * range of the table......
	 */
	ctp = *((chan_tab_t **)chanid);

	/* We should have multiple callers for a particular channel,
	 * an interrupt doesn't affect this pointer nor the descriptor,
	 * so no locking should be needed.
	 */
	dp = ctp->get_ptr;

	/* If the descriptor is valid, we are way ahead of the DMA
	 * engine, so just return an error condition.
	 */
	if (dp->dscr_cmd0 & DSCR_CMD0_V)
		return 0;

	/* Return buffer address and byte count.
	*/
	*buf = (void *)(phys_to_virt(dp->dscr_dest0));
	*nbytes = dp->dscr_cmd1;
	rv = dp->dscr_stat;

	/* Get next descriptor pointer.
	*/
	ctp->get_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));

	/* return something not zero.
	*/
	return rv;
}
예제 #11
0
파일: dbdma.c 프로젝트: 0x7f454c46/linux
void *au1xxx_ddma_get_nextptr_virt(au1x_ddma_desc_t *dp)
{
	return phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr));
}