diff options
| author | Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> | 2011-09-30 20:07:38 +0900 | 
|---|---|---|
| committer | Felipe Balbi <balbi@ti.com> | 2011-10-13 20:38:39 +0300 | 
| commit | b8a56e17e18cca2402b390c10b8d7f3cd0f6265b (patch) | |
| tree | 7587857c374fd360257814b24ed83d96e3b0019d | |
| parent | 12158f4280b4d42ef03b70a47d11b48dd8aad511 (diff) | |
| download | olio-linux-3.10-b8a56e17e18cca2402b390c10b8d7f3cd0f6265b.tar.xz olio-linux-3.10-b8a56e17e18cca2402b390c10b8d7f3cd0f6265b.zip  | |
usb: gadget: r8a66597-udc: add support for SUDMAC
SH7757 has a USB function with internal DMA controller (SUDMAC).
This patch supports the SUDMAC. The SUDMAC is incompatible with
general-purpose DMAC. So, it doesn't use dmaengine.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
| -rw-r--r-- | drivers/usb/gadget/r8a66597-udc.c | 364 | ||||
| -rw-r--r-- | drivers/usb/gadget/r8a66597-udc.h | 26 | ||||
| -rw-r--r-- | include/linux/usb/r8a66597.h | 60 | 
3 files changed, 430 insertions, 20 deletions
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c index 34abb12a88e..035879b98dd 100644 --- a/drivers/usb/gadget/r8a66597-udc.c +++ b/drivers/usb/gadget/r8a66597-udc.c @@ -18,13 +18,14 @@  #include <linux/clk.h>  #include <linux/err.h>  #include <linux/slab.h> +#include <linux/dma-mapping.h>  #include <linux/usb/ch9.h>  #include <linux/usb/gadget.h>  #include "r8a66597-udc.h" -#define DRIVER_VERSION	"2009-08-18" +#define DRIVER_VERSION	"2011-09-26"  static const char udc_name[] = "r8a66597_udc";  static const char *r8a66597_ep_name[] = { @@ -184,6 +185,54 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)  	}  } +static void control_reg_sqset(struct r8a66597 *r8a66597, u16 pipenum) +{ +	unsigned long offset; + +	pipe_stop(r8a66597, pipenum); + +	if (pipenum == 0) { +		r8a66597_bset(r8a66597, SQSET, DCPCTR); +	} else if (pipenum < R8A66597_MAX_NUM_PIPE) { +		offset = get_pipectr_addr(pipenum); +		r8a66597_bset(r8a66597, SQSET, offset); +	} else { +		dev_err(r8a66597_to_dev(r8a66597), +			"unexpect pipe num(%d)\n", pipenum); +	} +} + +static u16 control_reg_sqmon(struct r8a66597 *r8a66597, u16 pipenum) +{ +	unsigned long offset; + +	if (pipenum == 0) { +		return r8a66597_read(r8a66597, DCPCTR) & SQMON; +	} else if (pipenum < R8A66597_MAX_NUM_PIPE) { +		offset = get_pipectr_addr(pipenum); +		return r8a66597_read(r8a66597, offset) & SQMON; +	} else { +		dev_err(r8a66597_to_dev(r8a66597), +			"unexpect pipe num(%d)\n", pipenum); +	} + +	return 0; +} + +static u16 save_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum) +{ +	return control_reg_sqmon(r8a66597, pipenum); +} + +static void restore_usb_toggle(struct r8a66597 *r8a66597, u16 pipenum, +			       u16 toggle) +{ +	if (toggle) +		control_reg_sqset(r8a66597, pipenum); +	else +		control_reg_sqclr(r8a66597, pipenum); +} +  static inline int get_buffer_size(struct r8a66597 *r8a66597, u16 pipenum)  {  	u16 tmp; @@ -220,18 +269,51 @@ static inline unsigned short mbw_value(struct r8a66597 *r8a66597)  		return MBW_16;  } +static void r8a66597_change_curpipe(struct r8a66597 *r8a66597, u16 pipenum, +				    u16 isel, u16 fifosel) +{ +	u16 tmp, mask, loop; +	int i = 0; + +	if (!pipenum) { +		mask = ISEL | CURPIPE; +		loop = isel; +	} else { +		mask = CURPIPE; +		loop = pipenum; +	} +	r8a66597_mdfy(r8a66597, loop, mask, fifosel); + +	do { +		tmp = r8a66597_read(r8a66597, fifosel); +		if (i++ > 1000000) { +			dev_err(r8a66597_to_dev(r8a66597), +				"r8a66597: register%x, loop %x " +				"is timeout\n", fifosel, loop); +			break; +		} +		ndelay(1); +	} while ((tmp & mask) != loop); +} +  static inline void pipe_change(struct r8a66597 *r8a66597, u16 pipenum)  {  	struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum];  	if (ep->use_dma) -		return; +		r8a66597_bclr(r8a66597, DREQE, ep->fifosel);  	r8a66597_mdfy(r8a66597, pipenum, CURPIPE, ep->fifosel);  	ndelay(450); -	r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); +	if (r8a66597_is_sudmac(r8a66597) && ep->use_dma) +		r8a66597_bclr(r8a66597, mbw_value(r8a66597), ep->fifosel); +	else +		r8a66597_bset(r8a66597, mbw_value(r8a66597), ep->fifosel); + +	if (ep->use_dma) +		r8a66597_bset(r8a66597, DREQE, ep->fifosel);  }  static int pipe_buffer_setting(struct r8a66597 *r8a66597, @@ -336,9 +418,15 @@ static void r8a66597_ep_setting(struct r8a66597 *r8a66597,  	ep->fifoaddr = CFIFO;  	ep->fifosel = CFIFOSEL;  	ep->fifoctr = CFIFOCTR; -	ep->fifotrn = 0;  	ep->pipectr = get_pipectr_addr(pipenum); +	if (is_bulk_pipe(pipenum) || is_isoc_pipe(pipenum)) { +		ep->pipetre = get_pipetre_addr(pipenum); +		ep->pipetrn = get_pipetrn_addr(pipenum); +	} else { +		ep->pipetre = 0; +		ep->pipetrn = 0; +	}  	ep->pipenum = pipenum;  	ep->ep.maxpacket = usb_endpoint_maxp(desc);  	r8a66597->pipenum2ep[pipenum] = ep; @@ -498,6 +586,124 @@ static void start_ep0_write(struct r8a66597_ep *ep,  	}  } +static void disable_fifosel(struct r8a66597 *r8a66597, u16 pipenum, +			    u16 fifosel) +{ +	u16 tmp; + +	tmp = r8a66597_read(r8a66597, fifosel) & CURPIPE; +	if (tmp == pipenum) +		r8a66597_change_curpipe(r8a66597, 0, 0, fifosel); +} + +static void change_bfre_mode(struct r8a66597 *r8a66597, u16 pipenum, +			     int enable) +{ +	struct r8a66597_ep *ep = r8a66597->pipenum2ep[pipenum]; +	u16 tmp, toggle; + +	/* check current BFRE bit */ +	r8a66597_write(r8a66597, pipenum, PIPESEL); +	tmp = r8a66597_read(r8a66597, PIPECFG) & R8A66597_BFRE; +	if ((enable && tmp) || (!enable && !tmp)) +		return; + +	/* change BFRE bit */ +	pipe_stop(r8a66597, pipenum); +	disable_fifosel(r8a66597, pipenum, CFIFOSEL); +	disable_fifosel(r8a66597, pipenum, D0FIFOSEL); +	disable_fifosel(r8a66597, pipenum, D1FIFOSEL); + +	toggle = save_usb_toggle(r8a66597, pipenum); + +	r8a66597_write(r8a66597, pipenum, PIPESEL); +	if (enable) +		r8a66597_bset(r8a66597, R8A66597_BFRE, PIPECFG); +	else +		r8a66597_bclr(r8a66597, R8A66597_BFRE, PIPECFG); + +	/* initialize for internal BFRE flag */ +	r8a66597_bset(r8a66597, ACLRM, ep->pipectr); +	r8a66597_bclr(r8a66597, ACLRM, ep->pipectr); + +	restore_usb_toggle(r8a66597, pipenum, toggle); +} + +static int sudmac_alloc_channel(struct r8a66597 *r8a66597, +				struct r8a66597_ep *ep, +				struct r8a66597_request *req) +{ +	struct r8a66597_dma *dma; + +	if (!r8a66597_is_sudmac(r8a66597)) +		return -ENODEV; + +	/* Check transfer type */ +	if (!is_bulk_pipe(ep->pipenum)) +		return -EIO; + +	if (r8a66597->dma.used) +		return -EBUSY; + +	/* set SUDMAC parameters */ +	dma = &r8a66597->dma; +	dma->used = 1; +	if (ep->desc->bEndpointAddress & USB_DIR_IN) { +		dma->dir = 1; +	} else { +		dma->dir = 0; +		change_bfre_mode(r8a66597, ep->pipenum, 1); +	} + +	/* set r8a66597_ep paramters */ +	ep->use_dma = 1; +	ep->dma = dma; +	ep->fifoaddr = D0FIFO; +	ep->fifosel = D0FIFOSEL; +	ep->fifoctr = D0FIFOCTR; + +	/* dma mapping */ +	req->req.dma = dma_map_single(r8a66597_to_dev(ep->r8a66597), +				req->req.buf, req->req.length, +				dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + +	return 0; +} + +static void sudmac_free_channel(struct r8a66597 *r8a66597, +				struct r8a66597_ep *ep, +				struct r8a66597_request *req) +{ +	if (!r8a66597_is_sudmac(r8a66597)) +		return; + +	dma_unmap_single(r8a66597_to_dev(ep->r8a66597), +			 req->req.dma, req->req.length, +			 ep->dma->dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + +	r8a66597_bclr(r8a66597, DREQE, ep->fifosel); +	r8a66597_change_curpipe(r8a66597, 0, 0, ep->fifosel); + +	ep->dma->used = 0; +	ep->use_dma = 0; +	ep->fifoaddr = CFIFO; +	ep->fifosel = CFIFOSEL; +	ep->fifoctr = CFIFOCTR; +} + +static void sudmac_start(struct r8a66597 *r8a66597, struct r8a66597_ep *ep, +			 struct r8a66597_request *req) +{ +	BUG_ON(req->req.length == 0); + +	r8a66597_sudmac_write(r8a66597, LBA_WAIT, CH0CFG); +	r8a66597_sudmac_write(r8a66597, req->req.dma, CH0BA); +	r8a66597_sudmac_write(r8a66597, req->req.length, CH0BBC); +	r8a66597_sudmac_write(r8a66597, CH0ENDE, DINTCTRL); + +	r8a66597_sudmac_write(r8a66597, DEN, CH0DEN); +} +  static void start_packet_write(struct r8a66597_ep *ep,  				struct r8a66597_request *req)  { @@ -508,11 +714,29 @@ static void start_packet_write(struct r8a66597_ep *ep,  	disable_irq_empty(r8a66597, ep->pipenum);  	pipe_start(r8a66597, ep->pipenum); -	tmp = r8a66597_read(r8a66597, ep->fifoctr); -	if (unlikely((tmp & FRDY) == 0)) -		pipe_irq_enable(r8a66597, ep->pipenum); -	else -		irq_packet_write(ep, req); +	if (req->req.length == 0) { +		transfer_complete(ep, req, 0); +	} else { +		r8a66597_write(r8a66597, ~(1 << ep->pipenum), BRDYSTS); +		if (sudmac_alloc_channel(r8a66597, ep, req) < 0) { +			/* PIO mode */ +			pipe_change(r8a66597, ep->pipenum); +			disable_irq_empty(r8a66597, ep->pipenum); +			pipe_start(r8a66597, ep->pipenum); +			tmp = r8a66597_read(r8a66597, ep->fifoctr); +			if (unlikely((tmp & FRDY) == 0)) +				pipe_irq_enable(r8a66597, ep->pipenum); +			else +				irq_packet_write(ep, req); +		} else { +			/* DMA mode */ +			pipe_change(r8a66597, ep->pipenum); +			disable_irq_nrdy(r8a66597, ep->pipenum); +			pipe_start(r8a66597, ep->pipenum); +			enable_irq_nrdy(r8a66597, ep->pipenum); +			sudmac_start(r8a66597, ep, req); +		} +	}  }  static void start_packet_read(struct r8a66597_ep *ep, @@ -527,17 +751,26 @@ static void start_packet_read(struct r8a66597_ep *ep,  		pipe_start(r8a66597, pipenum);  		pipe_irq_enable(r8a66597, pipenum);  	} else { -		if (ep->use_dma) { -			r8a66597_bset(r8a66597, TRCLR, ep->fifosel); -			pipe_change(r8a66597, pipenum); -			r8a66597_bset(r8a66597, TRENB, ep->fifosel); +		pipe_stop(r8a66597, pipenum); +		if (ep->pipetre) { +			enable_irq_nrdy(r8a66597, pipenum); +			r8a66597_write(r8a66597, TRCLR, ep->pipetre);  			r8a66597_write(r8a66597, -				(req->req.length + ep->ep.maxpacket - 1) -					/ ep->ep.maxpacket, -				ep->fifotrn); +				DIV_ROUND_UP(req->req.length, ep->ep.maxpacket), +				ep->pipetrn); +			r8a66597_bset(r8a66597, TRENB, ep->pipetre); +		} + +		if (sudmac_alloc_channel(r8a66597, ep, req) < 0) { +			/* PIO mode */ +			change_bfre_mode(r8a66597, ep->pipenum, 0); +			pipe_start(r8a66597, pipenum);	/* trigger once */ +			pipe_irq_enable(r8a66597, pipenum); +		} else { +			pipe_change(r8a66597, pipenum); +			sudmac_start(r8a66597, ep, req); +			pipe_start(r8a66597, pipenum);	/* trigger once */  		} -		pipe_start(r8a66597, pipenum);	/* trigger once */ -		pipe_irq_enable(r8a66597, pipenum);  	}  } @@ -694,6 +927,9 @@ __acquires(r8a66597->lock)  	if (!list_empty(&ep->queue))  		restart = 1; +	if (ep->use_dma) +		sudmac_free_channel(ep->r8a66597, ep, req); +  	spin_unlock(&ep->r8a66597->lock);  	req->req.complete(&ep->ep, &req->req);  	spin_lock(&ep->r8a66597->lock); @@ -1170,6 +1406,65 @@ __acquires(r8a66597->lock)  	}  } +static void sudmac_finish(struct r8a66597 *r8a66597, struct r8a66597_ep *ep) +{ +	u16 pipenum; +	struct r8a66597_request *req; +	u32 len; +	int i = 0; + +	pipenum = ep->pipenum; +	pipe_change(r8a66597, pipenum); + +	while (!(r8a66597_read(r8a66597, ep->fifoctr) & FRDY)) { +		udelay(1); +		if (unlikely(i++ >= 10000)) {	/* timeout = 10 msec */ +			dev_err(r8a66597_to_dev(r8a66597), +				"%s: FRDY was not set (%d)\n", +				__func__, pipenum); +			return; +		} +	} + +	r8a66597_bset(r8a66597, BCLR, ep->fifoctr); +	req = get_request_from_ep(ep); + +	/* prepare parameters */ +	len = r8a66597_sudmac_read(r8a66597, CH0CBC); +	req->req.actual += len; + +	/* clear */ +	r8a66597_sudmac_write(r8a66597, CH0STCLR, DSTSCLR); + +	/* check transfer finish */ +	if ((!req->req.zero && (req->req.actual == req->req.length)) +			|| (len % ep->ep.maxpacket)) { +		if (ep->dma->dir) { +			disable_irq_ready(r8a66597, pipenum); +			enable_irq_empty(r8a66597, pipenum); +		} else { +			/* Clear the interrupt flag for next transfer */ +			r8a66597_write(r8a66597, ~(1 << pipenum), BRDYSTS); +			transfer_complete(ep, req, 0); +		} +	} +} + +static void r8a66597_sudmac_irq(struct r8a66597 *r8a66597) +{ +	u32 irqsts; +	struct r8a66597_ep *ep; +	u16 pipenum; + +	irqsts = r8a66597_sudmac_read(r8a66597, DINTSTS); +	if (irqsts & CH0ENDS) { +		r8a66597_sudmac_write(r8a66597, CH0ENDC, DINTSTSCLR); +		pipenum = (r8a66597_read(r8a66597, D0FIFOSEL) & CURPIPE); +		ep = r8a66597->pipenum2ep[pipenum]; +		sudmac_finish(r8a66597, ep); +	} +} +  static irqreturn_t r8a66597_irq(int irq, void *_r8a66597)  {  	struct r8a66597 *r8a66597 = _r8a66597; @@ -1180,6 +1475,9 @@ static irqreturn_t r8a66597_irq(int irq, void *_r8a66597)  	u16 savepipe;  	u16 mask0; +	if (r8a66597_is_sudmac(r8a66597)) +		r8a66597_sudmac_irq(r8a66597); +  	spin_lock(&r8a66597->lock);  	intsts0 = r8a66597_read(r8a66597, INTSTS0); @@ -1556,6 +1854,8 @@ static int __exit r8a66597_remove(struct platform_device *pdev)  	usb_del_gadget_udc(&r8a66597->gadget);  	del_timer_sync(&r8a66597->timer);  	iounmap(r8a66597->reg); +	if (r8a66597->pdata->sudmac) +		iounmap(r8a66597->sudmac_reg);  	free_irq(platform_get_irq(pdev, 0), r8a66597);  	r8a66597_free_request(&r8a66597->ep[0].ep, r8a66597->ep0_req);  #ifdef CONFIG_HAVE_CLK @@ -1572,6 +1872,26 @@ static void nop_completion(struct usb_ep *ep, struct usb_request *r)  {  } +static int __init r8a66597_sudmac_ioremap(struct r8a66597 *r8a66597, +					  struct platform_device *pdev) +{ +	struct resource *res; + +	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sudmac"); +	if (!res) { +		dev_err(&pdev->dev, "platform_get_resource error(sudmac).\n"); +		return -ENODEV; +	} + +	r8a66597->sudmac_reg = ioremap(res->start, resource_size(res)); +	if (r8a66597->sudmac_reg == NULL) { +		dev_err(&pdev->dev, "ioremap error(sudmac).\n"); +		return -ENOMEM; +	} + +	return 0; +} +  static int __init r8a66597_probe(struct platform_device *pdev)  {  #ifdef CONFIG_HAVE_CLK @@ -1649,6 +1969,11 @@ static int __init r8a66597_probe(struct platform_device *pdev)  		clk_enable(r8a66597->clk);  	}  #endif +	if (r8a66597->pdata->sudmac) { +		ret = r8a66597_sudmac_ioremap(r8a66597, pdev); +		if (ret < 0) +			goto clean_up2; +	}  	disable_controller(r8a66597); /* make sure controller is disabled */ @@ -1681,7 +2006,6 @@ static int __init r8a66597_probe(struct platform_device *pdev)  	r8a66597->ep[0].fifoaddr = CFIFO;  	r8a66597->ep[0].fifosel = CFIFOSEL;  	r8a66597->ep[0].fifoctr = CFIFOCTR; -	r8a66597->ep[0].fifotrn = 0;  	r8a66597->ep[0].pipectr = get_pipectr_addr(0);  	r8a66597->pipenum2ep[0] = &r8a66597->ep[0];  	r8a66597->epaddr2ep[0] = &r8a66597->ep[0]; @@ -1714,6 +2038,8 @@ clean_up2:  #endif  clean_up:  	if (r8a66597) { +		if (r8a66597->sudmac_reg) +			iounmap(r8a66597->sudmac_reg);  		if (r8a66597->ep0_req)  			r8a66597_free_request(&r8a66597->ep[0].ep,  						r8a66597->ep0_req); diff --git a/drivers/usb/gadget/r8a66597-udc.h b/drivers/usb/gadget/r8a66597-udc.h index 832ee59c8e4..8e3de61cd4b 100644 --- a/drivers/usb/gadget/r8a66597-udc.h +++ b/drivers/usb/gadget/r8a66597-udc.h @@ -43,6 +43,7 @@  	((pipenum >= R8A66597_BASE_PIPENUM_ISOC) && \  	 (pipenum < (R8A66597_BASE_PIPENUM_ISOC + R8A66597_MAX_NUM_ISOC))) +#define r8a66597_is_sudmac(r8a66597)	(r8a66597->pdata->sudmac)  struct r8a66597_pipe_info {  	u16	pipe;  	u16	epnum; @@ -60,6 +61,7 @@ struct r8a66597_request {  struct r8a66597_ep {  	struct usb_ep		ep;  	struct r8a66597		*r8a66597; +	struct r8a66597_dma	*dma;  	struct list_head	queue;  	unsigned		busy:1; @@ -75,13 +77,20 @@ struct r8a66597_ep {  	unsigned char		fifoaddr;  	unsigned char		fifosel;  	unsigned char		fifoctr; -	unsigned char		fifotrn;  	unsigned char		pipectr; +	unsigned char		pipetre; +	unsigned char		pipetrn; +}; + +struct r8a66597_dma { +	unsigned		used:1; +	unsigned		dir:1;	/* 1 = IN(write), 0 = OUT(read) */  };  struct r8a66597 {  	spinlock_t		lock;  	void __iomem		*reg; +	void __iomem		*sudmac_reg;  #ifdef CONFIG_HAVE_CLK  	struct clk *clk; @@ -94,6 +103,7 @@ struct r8a66597 {  	struct r8a66597_ep	ep[R8A66597_MAX_NUM_PIPE];  	struct r8a66597_ep	*pipenum2ep[R8A66597_MAX_NUM_PIPE];  	struct r8a66597_ep	*epaddr2ep[16]; +	struct r8a66597_dma	dma;  	struct timer_list	timer;  	struct usb_request	*ep0_req;	/* for internal request */ @@ -251,7 +261,21 @@ static inline u16 get_xtal_from_pdata(struct r8a66597_platdata *pdata)  	return clock;  } +static inline u32 r8a66597_sudmac_read(struct r8a66597 *r8a66597, +				       unsigned long offset) +{ +	return ioread32(r8a66597->sudmac_reg + offset); +} + +static inline void r8a66597_sudmac_write(struct r8a66597 *r8a66597, u32 val, +					 unsigned long offset) +{ +	iowrite32(val, r8a66597->sudmac_reg + offset); +} +  #define get_pipectr_addr(pipenum)	(PIPE1CTR + (pipenum - 1) * 2) +#define get_pipetre_addr(pipenum)	(PIPE1TRE + (pipenum - 1) * 4) +#define get_pipetrn_addr(pipenum)	(PIPE1TRN + (pipenum - 1) * 4)  #define enable_irq_ready(r8a66597, pipenum)	\  	enable_pipe_irq(r8a66597, pipenum, BRDYENB) diff --git a/include/linux/usb/r8a66597.h b/include/linux/usb/r8a66597.h index b6b8660d0c6..55805f9dcf2 100644 --- a/include/linux/usb/r8a66597.h +++ b/include/linux/usb/r8a66597.h @@ -48,6 +48,9 @@ struct r8a66597_platdata {  	/* (external controller only) set one = WR0_N shorted to WR1_N */  	unsigned	wr0_shorted_to_wr1:1; + +	/* set one = using SUDMAC */ +	unsigned	sudmac:1;  };  /* Register definitions */ @@ -417,5 +420,62 @@ struct r8a66597_platdata {  #define	USBSPD		0x00C0  #define	RTPORT		0x0001 +/* SUDMAC registers */ +#define CH0CFG		0x00 +#define CH1CFG		0x04 +#define CH0BA		0x10 +#define CH1BA		0x14 +#define CH0BBC		0x18 +#define CH1BBC		0x1C +#define CH0CA		0x20 +#define CH1CA		0x24 +#define CH0CBC		0x28 +#define CH1CBC		0x2C +#define CH0DEN		0x30 +#define CH1DEN		0x34 +#define DSTSCLR		0x38 +#define DBUFCTRL	0x3C +#define DINTCTRL	0x40 +#define DINTSTS		0x44 +#define DINTSTSCLR	0x48 +#define CH0SHCTRL	0x50 +#define CH1SHCTRL	0x54 + +/* SUDMAC Configuration Registers */ +#define SENDBUFM	0x1000 /* b12: Transmit Buffer Mode */ +#define RCVENDM		0x0100 /* b8: Receive Data Transfer End Mode */ +#define LBA_WAIT	0x0030 /* b5-4: Local Bus Access Wait */ + +/* DMA Enable Registers */ +#define DEN		0x0001 /* b1: DMA Transfer Enable */ + +/* DMA Status Clear Register */ +#define CH1STCLR	0x0002 /* b2: Ch1 DMA Status Clear */ +#define CH0STCLR	0x0001 /* b1: Ch0 DMA Status Clear */ + +/* DMA Buffer Control Register */ +#define CH1BUFW		0x0200 /* b9: Ch1 DMA Buffer Data Transfer Enable */ +#define CH0BUFW		0x0100 /* b8: Ch0 DMA Buffer Data Transfer Enable */ +#define CH1BUFS		0x0002 /* b2: Ch1 DMA Buffer Data Status */ +#define CH0BUFS		0x0001 /* b1: Ch0 DMA Buffer Data Status */ + +/* DMA Interrupt Control Register */ +#define CH1ERRE		0x0200 /* b9: Ch1 SHwy Res Err Detect Int Enable */ +#define CH0ERRE		0x0100 /* b8: Ch0 SHwy Res Err Detect Int Enable */ +#define CH1ENDE		0x0002 /* b2: Ch1 DMA Transfer End Int Enable */ +#define CH0ENDE		0x0001 /* b1: Ch0 DMA Transfer End Int Enable */ + +/* DMA Interrupt Status Register */ +#define CH1ERRS		0x0200 /* b9: Ch1 SHwy Res Err Detect Int Status */ +#define CH0ERRS		0x0100 /* b8: Ch0 SHwy Res Err Detect Int Status */ +#define CH1ENDS		0x0002 /* b2: Ch1 DMA Transfer End Int Status */ +#define CH0ENDS		0x0001 /* b1: Ch0 DMA Transfer End Int Status */ + +/* DMA Interrupt Status Clear Register */ +#define CH1ERRC		0x0200 /* b9: Ch1 SHwy Res Err Detect Int Stat Clear */ +#define CH0ERRC		0x0100 /* b8: Ch0 SHwy Res Err Detect Int Stat Clear */ +#define CH1ENDC		0x0002 /* b2: Ch1 DMA Transfer End Int Stat Clear */ +#define CH0ENDC		0x0001 /* b1: Ch0 DMA Transfer End Int Stat Clear */ +  #endif /* __LINUX_USB_R8A66597_H */  |