Re: [U-Boot] [PATCH 3/5] pxa255: Add USB CDC ACM driver

2012-08-09 Thread Marek Vasut
Dear Łukasz Dałek,

> Signed-off-by: Łukasz Dałek 
> ---
>  drivers/serial/usbtty.h |2 +
>  drivers/usb/gadget/pxa25x_udc.c |  939
> +++ include/usb/pxa25x_udc.h| 
>  65 +++
>  3 files changed, 1006 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/usb/gadget/pxa25x_udc.c
>  create mode 100644 include/usb/pxa25x_udc.h
> 
> diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
> index eb670da..632b54e 100644
> --- a/drivers/serial/usbtty.h
> +++ b/drivers/serial/usbtty.h
> @@ -31,6 +31,8 @@
>  #include 
>  #elif defined(CONFIG_MUSB_UDC)
>  #include 
> +#elif defined(CONFIG_CPU_PXA25X)
> +#include 
>  #elif defined(CONFIG_CPU_PXA27X)
>  #include 
>  #elif defined(CONFIG_DW_UDC)
> diff --git a/drivers/usb/gadget/pxa25x_udc.c
> b/drivers/usb/gadget/pxa25x_udc.c new file mode 100644
> index 000..4ff98cc
> --- /dev/null
> +++ b/drivers/usb/gadget/pxa25x_udc.c
> @@ -0,0 +1,939 @@
> +/*
> + * PXA25x USB device driver for u-boot.
> + *
> + * Copyright (C) 2012 Łukasz Dałek 
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + *
> + * based on drivers/usb/gadget/pxa27x_udc.c
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "ep0.h"
> +
> +struct pxa25x_endpoint {
> + u8  num;
> + u32 uddr;
> + u32 udccs;
> + u32 ubcr;
> +};
> +
> +static struct pxa25x_endpoint eps[] = {
> + { 0, UDDR0, UDCCS(0), 0 },
> + { 1, UDDR1, UDCCS(1), 0 },
> + { 2, UDDR2, UDCCS(2), UBCR2 },
> + { 3, UDDR3, UDCCS(3), 0 },
> + { 4, UDDR4, UDCCS(4), UBCR4 },
> + { 5, UDDR5, UDCCS(5), 0 },
> + { 6, UDDR6, UDCCS(6), 0 },
> + { 7, UDDR7, UDCCS(7), UBCR7 },
> + { 8, UDDR8, UDCCS(8), 0 },
> + { 9, UDDR9, UDCCS(9), UBCR9 },
> + { 10, UDDR10, UDCCS(10), 0 },
> + { 11, UDDR11, UDCCS(11), 0 },
> + { 12, UDDR12, UDCCS(12), UBCR12 },
> + { 13, UDDR13, UDCCS(13), 0 },
> + { 14, UDDR14, UDCCS(14), UBCR14 },
> + { 15, UDDR15, UDCCS(15), 0 },
> +};
> +
> +static struct usb_device_instance *udc_device;
> +static struct urb *ep0_urb;
> +static int ep0state = EP0_IDLE;
> +static int ep0laststate = EP0_IDLE;
> +
> +static inline void udc_set_reg(u32 reg, u32 mask)
> +{
> + u32 val;
> +
> + val = readl(reg);
> + val |= mask;
> + writel(val, reg);

set_bits_be32() does this

> +}
> +
> +static inline void udc_clear_reg(u32 reg, u32 mask)
> +{
> + u32 val;
> +
> + val = readl(reg);
> + val &= ~mask;
> + writel(val, reg);
> +}
> +
> +/* static void udc_dump_buffer(char *name, u8 *buf, int len)
> +{
> + usbdbg("%s - buf %p, len %d", name, buf, len);
> + print_buffer(0, buf, 1, len, 0);
> +} */
> +
> +static void udc_dump_buffer(u8 *data, int len)

Is this debug goo ? What does it do?

> +{
> + u8 buff[8 * 5 + 1]; /* 8 characters 0x??_ + null */
> + int i;
> +
> + for (i = 0; i < len; ++i) {
> + int n = i % 8;
> + buff[n * 5 + 0] = '0';
> + buff[n * 5 + 1] = 'x';
> +
> + u8 ch = data[i] >> 4;
> + buff[n * 5 + 2] = (ch < 10)?(ch + '0'):(ch - 10 + 'a');
> + ch = data[i] & 0xf;
> + buff[n * 5 + 3] = (ch < 10)?(ch + '0'):(ch - 10 + 'a');
> + buff[n * 5 + 4] = ' ';
> +
> + buff[n * 5 + 5] = 0x0;
> +
> + if (n == 7)
> + usbdbg("%s", buff);
> + }
> +
> +}
> +
> +static void udc_flush_fifo(struct usb_endpoint_instance *endpoint)
> +{
> + int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK,

Ok, this probably doesn't pass tools/checkpatch.pl right? Also, define it on 
two 
separate lines.

> + isout =
> + (endpoint->endpoint_address & USB_ENDPOINT_DIR_MASK) == 
USB_DIR_OUT;
> + int ep_type;
> + u32 val;
> +
> + if (ep_num > 15) {
> + usberr("%s: endpoint out of range %d", __func__, ep_num);

printf() or debug(), choose one.

> + return ;
> + }
> +
> + if (!ep_num) {
> + while (readl(UDCCS0) & UDCCS_CTRL_RNE)
> + readl(UDDR0);

How does this loop work? And no endless loops please.

> + writel(UDCCS_CTRL_FTF, UDCCS0);
> + usbdbg("flu

[U-Boot] [PATCH 3/5] pxa255: Add USB CDC ACM driver

2012-07-27 Thread Łukasz Dałek
Signed-off-by: Łukasz Dałek 
---
 drivers/serial/usbtty.h |2 +
 drivers/usb/gadget/pxa25x_udc.c |  939 +++
 include/usb/pxa25x_udc.h|   65 +++
 3 files changed, 1006 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/pxa25x_udc.c
 create mode 100644 include/usb/pxa25x_udc.h

diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index eb670da..632b54e 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -31,6 +31,8 @@
 #include 
 #elif defined(CONFIG_MUSB_UDC)
 #include 
+#elif defined(CONFIG_CPU_PXA25X)
+#include 
 #elif defined(CONFIG_CPU_PXA27X)
 #include 
 #elif defined(CONFIG_DW_UDC)
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c
new file mode 100644
index 000..4ff98cc
--- /dev/null
+++ b/drivers/usb/gadget/pxa25x_udc.c
@@ -0,0 +1,939 @@
+/*
+ * PXA25x USB device driver for u-boot.
+ *
+ * Copyright (C) 2012 Łukasz Dałek 
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ * based on drivers/usb/gadget/pxa27x_udc.c
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "ep0.h"
+
+struct pxa25x_endpoint {
+   u8  num;
+   u32 uddr;
+   u32 udccs;
+   u32 ubcr;
+};
+
+static struct pxa25x_endpoint eps[] = {
+   { 0, UDDR0, UDCCS(0), 0 },
+   { 1, UDDR1, UDCCS(1), 0 },
+   { 2, UDDR2, UDCCS(2), UBCR2 },
+   { 3, UDDR3, UDCCS(3), 0 },
+   { 4, UDDR4, UDCCS(4), UBCR4 },
+   { 5, UDDR5, UDCCS(5), 0 },
+   { 6, UDDR6, UDCCS(6), 0 },
+   { 7, UDDR7, UDCCS(7), UBCR7 },
+   { 8, UDDR8, UDCCS(8), 0 },
+   { 9, UDDR9, UDCCS(9), UBCR9 },
+   { 10, UDDR10, UDCCS(10), 0 },
+   { 11, UDDR11, UDCCS(11), 0 },
+   { 12, UDDR12, UDCCS(12), UBCR12 },
+   { 13, UDDR13, UDCCS(13), 0 },
+   { 14, UDDR14, UDCCS(14), UBCR14 },
+   { 15, UDDR15, UDCCS(15), 0 },
+};
+
+static struct usb_device_instance *udc_device;
+static struct urb *ep0_urb;
+static int ep0state = EP0_IDLE;
+static int ep0laststate = EP0_IDLE;
+
+static inline void udc_set_reg(u32 reg, u32 mask)
+{
+   u32 val;
+
+   val = readl(reg);
+   val |= mask;
+   writel(val, reg);
+}
+
+static inline void udc_clear_reg(u32 reg, u32 mask)
+{
+   u32 val;
+
+   val = readl(reg);
+   val &= ~mask;
+   writel(val, reg);
+}
+
+/* static void udc_dump_buffer(char *name, u8 *buf, int len)
+{
+   usbdbg("%s - buf %p, len %d", name, buf, len);
+   print_buffer(0, buf, 1, len, 0);
+} */
+
+static void udc_dump_buffer(u8 *data, int len)
+{
+   u8 buff[8 * 5 + 1]; /* 8 characters 0x??_ + null */
+   int i;
+
+   for (i = 0; i < len; ++i) {
+   int n = i % 8;
+   buff[n * 5 + 0] = '0';
+   buff[n * 5 + 1] = 'x';
+
+   u8 ch = data[i] >> 4;
+   buff[n * 5 + 2] = (ch < 10)?(ch + '0'):(ch - 10 + 'a');
+   ch = data[i] & 0xf;
+   buff[n * 5 + 3] = (ch < 10)?(ch + '0'):(ch - 10 + 'a');
+   buff[n * 5 + 4] = ' ';
+
+   buff[n * 5 + 5] = 0x0;
+
+   if (n == 7)
+   usbdbg("%s", buff);
+   }
+
+}
+
+static void udc_flush_fifo(struct usb_endpoint_instance *endpoint)
+{
+   int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK,
+   isout = 
+   (endpoint->endpoint_address & USB_ENDPOINT_DIR_MASK) == 
USB_DIR_OUT;
+   int ep_type;
+   u32 val;
+
+   if (ep_num > 15) {
+   usberr("%s: endpoint out of range %d", __func__, ep_num);
+   return ;
+   }
+
+   if (!ep_num) {
+   while (readl(UDCCS0) & UDCCS_CTRL_RNE)
+   readl(UDDR0);
+   writel(UDCCS_CTRL_FTF, UDCCS0);
+   usbdbg("flushed endpoint 0 (udccs0 0x%02X)",
+   readl(UDCCS0) & 0xff);
+   return ;
+   }
+
+   if (isout) {
+   while (readl(eps[ep_num].udccs) & UDCCS_BULK_OUT_RNE)
+   readl(eps[ep_num].uddr);
+   usbdbg("out endpoint %d flushed", ep_num);
+   return ;
+   }
+
+   ep_type = endpoint->tx_attributes;
+
+   val = UDCCS_BULK_IN_TPC | UDCCS_BULK_IN_FTF | UDCCS_BULK_IN_TUR;
+