From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marek Vasut Date: Thu, 9 Aug 2012 22:40:55 +0200 Subject: [U-Boot] [PATCH 3/5] pxa255: Add USB CDC ACM driver In-Reply-To: <1343410321-7361-1-git-send-email-luk0104@gmail.com> References: <1343410321-7361-1-git-send-email-luk0104@gmail.com> Message-ID: <201208092240.55466.marex@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 0000000..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("flushed endpoint 0 (udccs0 0x%02X)", > + readl(UDCCS0) & 0xff); debug() > + 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; > + if (ep_type == USB_ENDPOINT_XFER_BULK || > + ep_type == USB_ENDPOINT_XFER_INT) { > + val |= UDCCS_BULK_IN_SST; > + } > + writel(val, eps[ep_num].udccs); > + usbdbg("in endpoint %d flushed", ep_num); > +} > + > +/* static void udc_stall_ep(int num) > +{ > + writel(UDCCS_BULK_IN_FST, eps[num].udccs); > + usbdbg("forced stall on ep %d", num); > +} */ Dead code > +static int udc_write_urb(struct usb_endpoint_instance *endpoint) > +{ > + int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; > + int i, length; > + struct urb *urb = endpoint->tx_urb; > + u8 *data; > + /* int timeout = 2000; */ > + > + if (!urb) > + return -1; > + > + if (!urb->actual_length) { > + usbdbg("clearing tpc and tur bits"); > + writel(UDCCS_BULK_IN_TPC | UDCCS_BULK_IN_TUR, eps[ep_num].udccs); > + return -1; > + } > + > + > + /* FIXME: check TFS bit for udc transsmion ready */ So fix it > + usbdbg("urb->actual_length %d, endpoint->sent %d, endpoint 0x%p, " > + "urb 0x%p", urb->actual_length, endpoint->sent, > + endpoint, urb); > + > + length = MIN(urb->actual_length - endpoint->sent, > endpoint->tx_packetSize); + if (length <= 0) { > + usbdbg("nothing to sent"); > + return -1; > + } > + > + /* clear tpc and tur bit */ > + writel(UDCCS_BULK_IN_TPC | UDCCS_BULK_IN_TUR, eps[ep_num].udccs); > + > + data = (u8 *)urb->buffer + endpoint->sent; > + for (i = 0; i < length; ++i) > + writel(data[i], eps[ep_num].uddr); > + > + usbdbg("prepare to sent %d bytes on ep %d, udccs 0x%02X", > + length, ep_num, readl(eps[ep_num].udccs)); > + > + /* short packet? */ > + if (length != endpoint->tx_packetSize) { > + usbdbg("ep_num %d, sending short packet", ep_num); > + writel(UDCCS_BULK_IN_TSP, eps[ep_num].udccs); > + } > + > + /* wait for data */ > +#if 0 > + while ( !(readl(eps[ep_num].udccs) & UDCCS_BULK_IN_TPC) ) { This passed checkpatch? C++ comments up ahead etc. I don't review any further, please lint the patches with checkpatch and resubmit. Thanks! [...]