* [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC
@ 2011-09-26 8:43 Yoshihiro Shimoda
2011-09-30 8:17 ` Felipe Balbi
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Yoshihiro Shimoda @ 2011-09-26 8:43 UTC (permalink / raw)
To: linux-sh
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>
---
drivers/usb/gadget/r8a66597-udc.c | 359 +++++++++++++++++++++++++++++++++++--
drivers/usb/gadget/r8a66597-udc.h | 26 +++-
include/linux/usb/r8a66597.h | 60 ++++++
3 files changed, 425 insertions(+), 20 deletions(-)
diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
index cd2cd16..4d27cb3 100644
--- a/drivers/usb/gadget/r8a66597-udc.c
+++ b/drivers/usb/gadget/r8a66597-udc.c
@@ -28,13 +28,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[] = {
@@ -186,6 +187,51 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
printk(KERN_ERR "unexpect pipe num(%d)\n", 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
+ printk(KERN_ERR "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
+ printk(KERN_ERR "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;
@@ -222,18 +268,50 @@ 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) {
+ printk(KERN_ERR "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,
@@ -337,9 +415,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 = le16_to_cpu(desc->wMaxPacketSize);
r8a66597->pipenum2ep[pipenum] = ep;
@@ -495,6 +579,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(ep->r8a66597->gadget.dev.parent,
+ 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(ep->r8a66597->gadget.dev.parent,
+ 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)
{
@@ -505,11 +707,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,
@@ -524,17 +744,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);
}
}
@@ -690,6 +919,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);
@@ -1163,6 +1395,64 @@ __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 */
+ printk(KERN_ERR "%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;
@@ -1173,6 +1463,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);
@@ -1547,6 +1840,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
@@ -1563,6 +1858,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
@@ -1640,6 +1955,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 */
@@ -1672,7 +1992,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];
@@ -1705,6 +2024,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 37d0dd5..93376f7 100644
--- a/drivers/usb/gadget/r8a66597-udc.h
+++ b/drivers/usb/gadget/r8a66597-udc.h
@@ -53,6 +53,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;
@@ -70,6 +71,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;
@@ -85,13 +87,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;
@@ -104,6 +113,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 */
@@ -260,7 +270,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 b6b8660..55805f9 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 */
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC
2011-09-26 8:43 [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC Yoshihiro Shimoda
@ 2011-09-30 8:17 ` Felipe Balbi
2011-09-30 9:49 ` Yoshihiro Shimoda
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Felipe Balbi @ 2011-09-30 8:17 UTC (permalink / raw)
To: linux-sh
[-- Attachment #1: Type: text/plain, Size: 2032 bytes --]
Hi,
On Mon, Sep 26, 2011 at 05:43:02PM +0900, Yoshihiro Shimoda wrote:
> 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>
> ---
> drivers/usb/gadget/r8a66597-udc.c | 359 +++++++++++++++++++++++++++++++++++--
> drivers/usb/gadget/r8a66597-udc.h | 26 +++-
> include/linux/usb/r8a66597.h | 60 ++++++
> 3 files changed, 425 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/usb/gadget/r8a66597-udc.c b/drivers/usb/gadget/r8a66597-udc.c
> index cd2cd16..4d27cb3 100644
> --- a/drivers/usb/gadget/r8a66597-udc.c
> +++ b/drivers/usb/gadget/r8a66597-udc.c
> @@ -28,13 +28,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[] = {
> @@ -186,6 +187,51 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
> printk(KERN_ERR "unexpect pipe num(%d)\n", 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
> + printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
according to CodingStyle, if one branch as braces, all of them should
have. Also, try to avoid printk(), I guess you have a *dev here to use
dev_err(). Besides this, I guess it looks fine.
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC
2011-09-26 8:43 [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC Yoshihiro Shimoda
2011-09-30 8:17 ` Felipe Balbi
@ 2011-09-30 9:49 ` Yoshihiro Shimoda
2011-09-30 9:55 ` Felipe Balbi
2011-09-30 10:48 ` Yoshihiro Shimoda
3 siblings, 0 replies; 5+ messages in thread
From: Yoshihiro Shimoda @ 2011-09-30 9:49 UTC (permalink / raw)
To: linux-sh
Hi,
2011/09/30 17:17, Felipe Balbi wrote:
> Hi,
>
< snip >
> On Mon, Sep 26, 2011 at 05:43:02PM +0900, Yoshihiro Shimoda wrote:
>> @@ -186,6 +187,51 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
>> printk(KERN_ERR "unexpect pipe num(%d)\n", 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
>> + printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
>
> according to CodingStyle, if one branch as braces, all of them should
> have. Also, try to avoid printk(), I guess you have a *dev here to use
> dev_err(). Besides this, I guess it looks fine.
>
I knew the rule, but I mistook the code...
I will fix it. And I also use dev_err() instead of printk().
Best regards,
Yoshihiro Shimoda
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC
2011-09-26 8:43 [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC Yoshihiro Shimoda
2011-09-30 8:17 ` Felipe Balbi
2011-09-30 9:49 ` Yoshihiro Shimoda
@ 2011-09-30 9:55 ` Felipe Balbi
2011-09-30 10:48 ` Yoshihiro Shimoda
3 siblings, 0 replies; 5+ messages in thread
From: Felipe Balbi @ 2011-09-30 9:55 UTC (permalink / raw)
To: linux-sh
[-- Attachment #1: Type: text/plain, Size: 1322 bytes --]
Hi,
On Fri, Sep 30, 2011 at 06:49:15PM +0900, Yoshihiro Shimoda wrote:
> Hi,
> 2011/09/30 17:17, Felipe Balbi wrote:
> > Hi,
> >
> < snip >
> > On Mon, Sep 26, 2011 at 05:43:02PM +0900, Yoshihiro Shimoda wrote:
> >> @@ -186,6 +187,51 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
> >> printk(KERN_ERR "unexpect pipe num(%d)\n", 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
> >> + printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
> >
> > according to CodingStyle, if one branch as braces, all of them should
> > have. Also, try to avoid printk(), I guess you have a *dev here to use
> > dev_err(). Besides this, I guess it looks fine.
> >
>
> I knew the rule, but I mistook the code...
> I will fix it. And I also use dev_err() instead of printk().
it might also be wise to add a patch, before this one, converting
printk() to dev_* macros, I guess ;-)
--
balbi
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 490 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC
2011-09-26 8:43 [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC Yoshihiro Shimoda
` (2 preceding siblings ...)
2011-09-30 9:55 ` Felipe Balbi
@ 2011-09-30 10:48 ` Yoshihiro Shimoda
3 siblings, 0 replies; 5+ messages in thread
From: Yoshihiro Shimoda @ 2011-09-30 10:48 UTC (permalink / raw)
To: linux-sh
Hi,
2011/09/30 18:55, Felipe Balbi wrote:
> Hi,
>
> On Fri, Sep 30, 2011 at 06:49:15PM +0900, Yoshihiro Shimoda wrote:
>> Hi,
>> 2011/09/30 17:17, Felipe Balbi wrote:
>>> Hi,
>>>
>> < snip >
>>> On Mon, Sep 26, 2011 at 05:43:02PM +0900, Yoshihiro Shimoda wrote:
>>>> @@ -186,6 +187,51 @@ static inline void control_reg_sqclr(struct r8a66597 *r8a66597, u16 pipenum)
>>>> printk(KERN_ERR "unexpect pipe num(%d)\n", 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
>>>> + printk(KERN_ERR "unexpect pipe num(%d)\n", pipenum);
>>>
>>> according to CodingStyle, if one branch as braces, all of them should
>>> have. Also, try to avoid printk(), I guess you have a *dev here to use
>>> dev_err(). Besides this, I guess it looks fine.
>>>
>>
>> I knew the rule, but I mistook the code...
>> I will fix it. And I also use dev_err() instead of printk().
>
> it might also be wise to add a patch, before this one, converting
> printk() to dev_* macros, I guess ;-)
>
I think so. :)
I wrote such patch and I will submit it soon.
Best regards,
Yoshihiro Shimoda
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2011-09-30 10:48 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-26 8:43 [PATCH 2/2] usb: r8a66597-udc: add support for SUDMAC Yoshihiro Shimoda
2011-09-30 8:17 ` Felipe Balbi
2011-09-30 9:49 ` Yoshihiro Shimoda
2011-09-30 9:55 ` Felipe Balbi
2011-09-30 10:48 ` Yoshihiro Shimoda
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.