All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tom <Tom.Rix@windriver.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v4 06/12] SPEAr : usbd driver support for SPEAr SoCs
Date: Wed, 13 Jan 2010 07:18:46 -0600	[thread overview]
Message-ID: <4B4DC836.5050509@windriver.com> (raw)



SPEAr SoCs contain a synopsys usb device controller.
USB Device IP can work in 2 modes
- DMA mode
- Slave mode

The driver adds support only for slave mode operation of usb
device IP. This driver is used along with standard USBTTY
driver to obtain a tty interface over USB on the host

Signed-off-by: Vipin <vipin.kumar@st.com>
---
  drivers/serial/usbtty.h      |    2 +
  drivers/usb/gadget/Makefile  |    1 +
  drivers/usb/gadget/spr_udc.c | 1002 ++++++++++++++++++++++++++++++++++++++++++
  include/usb/spr_udc.h        |  227 ++++++++++
  4 files changed, 1232 insertions(+), 0 deletions(-)
  mode change 100644 => 100755 drivers/serial/usbtty.h
  mode change 100644 => 100755 drivers/usb/gadget/Makefile
  create mode 100755 drivers/usb/gadget/spr_udc.c
  create mode 100755 include/usb/spr_udc.h

<snip>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+
+#include <usbdevice.h>
+#include "ep0.h"
+#include <usb/spr_udc.h>
+#include <asm/arch/spr_misc.h>
+
+#define UDC_INIT_MDELAY		     80	/* Device settle delay */
ws
Some space before the '80'
+
+/* Some kind of debugging output... */
+#ifndef DEBUG_SPRUSBTTY
+#define UDCDBG(str)
+#define UDCDBGA(fmt, args...)
+#else
+#define UDCDBG(str) serial_printf(str "\n")
+#define UDCDBGA(fmt, args...) serial_printf(fmt "\n", ##args)
+#endif
+
+static struct urb *ep0_urb;
+static struct usb_device_instance *udc_device;
+
+static struct plug_regs *const plug_regs_p =
+    (struct plug_regs * const)CONFIG_SYS_PLUG_BASE;
+static struct udc_regs *const udc_regs_p =
+    (struct udc_regs * const)CONFIG_SYS_USBD_BASE;
+static struct udc_endp_regs *const outep_regs_p =
+    &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->out_regs[0];
+static struct udc_endp_regs *const inep_regs_p =
+    &((struct udc_regs * const)CONFIG_SYS_USBD_BASE)->in_regs[0];
+
Similar to other CONFIG_* register bases,
It may be better to move/rename the CONFIG_SYS_PLUG_BASE to
an asm/arch header file.


+/*
+ * udc_state_transition - Write the next packet to TxFIFO.

<snip>

  *
+ * This function must only be called with interrupts disabled.
+ */
+static void udc_state_transition(usb_device_state_t initial,
+				 usb_device_state_t final)
+{
+	if (initial < final) {
+		switch (initial) {
+		case STATE_ATTACHED:
+			usbd_device_event_irq(udc_device,
+					      DEVICE_HUB_CONFIGURED, 0);
+			if (final == STATE_POWERED)
+				break;
+		case STATE_POWERED:
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+			if (final == STATE_DEFAULT)
+				break;
+		case STATE_DEFAULT:
+			usbd_device_event_irq(udc_device,
+					      DEVICE_ADDRESS_ASSIGNED, 0);
+			if (final == STATE_ADDRESSED)
+				break;
+		case STATE_ADDRESSED:
+			usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
+		case STATE_CONFIGURED:
+			break;
+		default:
+			break;
+		}
+	} else if (initial > final) {
+		switch (initial) {
+		case STATE_CONFIGURED:
+			usbd_device_event_irq(udc_device,
+					      DEVICE_DE_CONFIGURED, 0);
+			if (final == STATE_ADDRESSED)
+				break;
+		case STATE_ADDRESSED:
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+			if (final == STATE_DEFAULT)
+				break;
+		case STATE_DEFAULT:
+			usbd_device_event_irq(udc_device,
+					      DEVICE_POWER_INTERRUPTION, 0);
+			if (final == STATE_POWERED)
+				break;
+		case STATE_POWERED:
+			usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
+		case STATE_ATTACHED:
+			break;
+		default:
+			break;
+		}
+	}
No panicing if the state transition is the default ?
+}
+

<snip>

+static void *get_fifo(int ep_num, int in)
+{
+	u32 *fifo_ptr = (u32 *)CONFIG_SYS_FIFO_BASE;
+
+	switch (ep_num) {
+	case 3:
+		fifo_ptr += readl(&inep_regs_p[1].endp_bsorfn);
+		/* break intentionally left out */
+
+	case 1:
+		fifo_ptr += readl(&inep_regs_p[0].endp_bsorfn);
+		/* break intentionally left out */
+
These EP's should be the #defined UDC_*_ENDPOINT

+	case 0:
+	default:
+		if (in) {
+			fifo_ptr +=
+			    readl(&outep_regs_p[2].endp_maxpacksize) >> 16;
+			/* break intentionally left out */
+		} else {
+			break;
+		}
+
+	case 2:
+		fifo_ptr += readl(&outep_regs_p[0].endp_maxpacksize) >> 16;
+		/* break intentionally left out */
+	}
+
+	return (void *)fifo_ptr;
+}
+
+static short usbgetpckfromfifo(int epNum, u8 *bufp, u32 len)
+{
+	u8 *fifo_ptr = (u8 *)get_fifo(epNum, 0);
+	u32 i, nw, nb;
+	u32 *wrdp;
+	u8 *bytp;
+
+	if (readl(&udc_regs_p->dev_stat) & DEV_STAT_RXFIFO_EMPTY)
+		return -1;
+
+	nw = len / sizeof(u32);
+	nb = len % sizeof(u32);
+
+	wrdp = (u32 *)bufp;
Does this work when bufp is unaligned ?
+	for (i = 0; i < nw; i++) {
+		writel(readl(fifo_ptr), wrdp);
+		wrdp++;
+	}
+
+	bytp = (u8 *)wrdp;
+	for (i = 0; i < nb; i++) {
+		writeb(readb(fifo_ptr), bytp);
+		fifo_ptr++;
+		bytp++;
+	}
+	readl(&outep_regs_p[epNum].write_done);
+
+	return 0;
The status of this function is never checked.
Choosing 'short' is also unusual.
Maybe this should be an int
+}
+
+static void usbputpcktofifo(int epNum, u8 *bufp, u32 len)
+{
+	u32 i, nw, nb;
+	u32 *wrdp;
+	u8 *bytp;
+	u8 *fifo_ptr = get_fifo(epNum, 1);
+
+	nw = len / sizeof(int);
+	nb = len % sizeof(int);
+	wrdp = (u32 *)bufp;
+	for (i = 0; i < nw; i++) {
+		writel(*wrdp, fifo_ptr);
+		wrdp++;
+	}
+
+	bytp = (u8 *)wrdp;
+	for (i = 0; i < nb; i++) {
+		writeb(*bytp, fifo_ptr);
+		fifo_ptr++;
+		bytp++;
+	}
+}

<snip>

+/*
+ * Handle TX transaction on non-ISO endpoint.
+ * The ep argument is a physical endpoint number for a non-ISO IN endpoint
+ * in the range 16 to 30.
+ */
+static void spear_udc_epn_tx(int ep)
+{
+	struct usb_endpoint_instance *endpoint = spear_find_ep(ep);

This can return NULL
check if (endpoint)

+
+	/*
+	 * We need to transmit a terminating zero-length packet now if
+	 * we have sent all of the data in this URB and the transfer
+	 * size was an exact multiple of the packet size.
+	 */
+	if (endpoint->tx_urb && endpoint->tx_urb->actual_length) {
+		if (endpoint->last == endpoint->tx_packetSize) {
+			/* handle zero length packet here */
+			writel(0x0, &inep_regs_p[ep].write_done);
+		}
+		/* retire the data that was just sent */
+		usbd_tx_complete(endpoint);
+		/*
+		 * Check to see if we have more data ready to transmit
+		 * now.
+		 */
+		if (endpoint->tx_urb && endpoint->tx_urb->actual_length) {
+			/* write data to FIFO */
+			spear_write_noniso_tx_fifo(endpoint);
+			writel(0x0, &inep_regs_p[ep].write_done);
+
+		} else if (endpoint->tx_urb
+			   && (endpoint->tx_urb->actual_length == 0)) {
+			/* udc_set_nak(ep); */
+		}
+	}
+}

<snip>
+	writel(val, &outep_regs_p[epid].endp_cntl);
+}
+
+/*******************************************************************
+ * SLAVE MODE ::
+ * Routines to acces RX/TX FIFOs directly.
+ *******************************************************************/
ws
change to proper multi-line comment.

diff --git a/include/usb/spr_udc.h b/include/usb/spr_udc.h
new file mode 100755
index 0000000..191c439
--- /dev/null
+++ b/include/usb/spr_udc.h
@@ -0,0 +1,227 @@
+/*
+ * (C) Copyright 2009
+ * Vipin Kumar, ST Micoelectronics, vipin.kumar at st.com.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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
+ */
+
+#ifndef __SPR_UDC_H
+#define __SPR_UDC_H
+
+/*****************************************************************************
+ * Defines for  USBD
+ *
+ * The udc_ahb controller has three AHB slaves:
+ *
+ * 1.  THe UDC registers
+ * 2.  The plug detect
+ * 3.  The RX/TX FIFO
+ *****************************************************************************/
ws
change to proper multi-line comment
+
+#define MAX_ENDPOINTS		16
+
+struct udc_endp_regs {
+	u32 endp_cntl;
+	u32 endp_status;
+	u32 endp_bsorfn;
+	u32 endp_maxpacksize;
+	u32 reserved_1;
+	u32 endp_desc_point;
+	u32 reserved_2;
+	u32 write_done;
+};
+
+/* Endpoint Control Register definitions */
+
+#define  ENDP_CNTL_STALL		0x00000001
+#define  ENDP_CNTL_FLUSH		0x00000002
+#define  ENDP_CNTL_SNOOP		0x00000004
+#define  ENDP_CNTL_POLL			0x00000008
+#define  ENDP_CNTL_CONTROL		0x00000000
+#define  ENDP_CNTL_ISO			0x00000010
+#define  ENDP_CNTL_BULK			0x00000020
+#define  ENDP_CNTL_INT			0x00000030
+#define  ENDP_CNTL_NAK			0x00000040
+#define  ENDP_CNTL_SNAK			0x00000080
+#define  ENDP_CNTL_CNAK			0x00000100
+#define  ENDP_CNTL_RRDY			0x00000200
+
+/* Endpoint Satus Register definitions */
+
+#define  ENDP_STATUS_PIDMSK		0x0000000f
+#define  ENDP_STATUS_OUTMSK		0x00000030
+#define  ENDP_STATUS_OUT_NONE		0x00000000
+#define  ENDP_STATUS_OUT_DATA		0x00000010
+#define  ENDP_STATUS_OUT_SETUP		0x00000020
+#define  ENDP_STATUS_IN			0x00000040
+#define  ENDP_STATUS_BUFFNAV		0x00000080
+#define  ENDP_STATUS_FATERR		0x00000100
+#define  ENDP_STATUS_HOSTBUSERR		0x00000200
+#define  ENDP_STATUS_TDC		0x00000400
+#define  ENDP_STATUS_RXPKTMSK		0x003ff800
+
+struct udc_regs {
+	struct udc_endp_regs in_regs[MAX_ENDPOINTS];
+	struct udc_endp_regs out_regs[MAX_ENDPOINTS];
+	u32 dev_conf;
+	u32 dev_cntl;
+	u32 dev_stat;
+	u32 dev_int;
+	u32 dev_int_mask;
+	u32 endp_int;
+	u32 endp_int_mask;
+	u32 reserved_3[0x39];
+	u32 reserved_4;		/* offset 0x500 */
+	u32 udc_endp_reg[MAX_ENDPOINTS];
+};
+
+/* Device Configuration Register definitions */
+
+#define  DEV_CONF_HS_SPEED		0x00000000
+#define  DEV_CONF_LS_SPEED		0x00000002
+#define  DEV_CONF_FS_SPEED		0x00000003
+#define  DEV_CONF_REMWAKEUP		0x00000004
+#define  DEV_CONF_SELFPOW		0x00000008
+#define  DEV_CONF_SYNCFRAME		0x00000010
+#define  DEV_CONF_PHYINT_8		0x00000020
+#define  DEV_CONF_PHYINT_16		0x00000000
+#define  DEV_CONF_UTMI_BIDIR		0x00000040
+#define  DEV_CONF_STATUS_STALL		0x00000080
+
+/* Device Control Register definitions */
+
+#define  DEV_CNTL_RESUME		0x00000001
+#define  DEV_CNTL_TFFLUSH		0x00000002
+#define  DEV_CNTL_RXDMAEN		0x00000004
+#define  DEV_CNTL_TXDMAEN		0x00000008
+#define  DEV_CNTL_DESCRUPD		0x00000010
+#define  DEV_CNTL_BIGEND		0x00000020
+#define  DEV_CNTL_BUFFILL		0x00000040
+#define  DEV_CNTL_TSHLDEN		0x00000080
+#define  DEV_CNTL_BURSTEN		0x00000100
+#define  DEV_CNTL_DMAMODE		0x00000200
+#define  DEV_CNTL_SOFTDISCONNECT	0x00000400
+#define  DEV_CNTL_SCALEDOWN		0x00000800
+#define  DEV_CNTL_BURSTLENU		0x00010000
+#define  DEV_CNTL_BURSTLENMSK		0x00ff0000
+#define  DEV_CNTL_TSHLDLENU		0x01000000
+#define  DEV_CNTL_TSHLDLENMSK		0xff000000
+
+/* Device Status Register definitions */
+
+#define  DEV_STAT_CFG			0x0000000f
+#define  DEV_STAT_INTF			0x000000f0
+#define  DEV_STAT_ALT			0x00000f00
+#define  DEV_STAT_SUSP			0x00001000
+#define  DEV_STAT_ENUM			0x00006000
+#define  DEV_STAT_ENUM_SPEED_HS		0x00000000
+#define  DEV_STAT_ENUM_SPEED_FS		0x00002000
+#define  DEV_STAT_ENUM_SPEED_LS		0x00004000
+#define  DEV_STAT_RXFIFO_EMPTY		0x00008000
+#define  DEV_STAT_PHY_ERR		0x00010000
+#define  DEV_STAT_TS			0xf0000000
+
+/* Device Interrupt Register definitions */
+
+#define  DEV_INT_MSK			0x0000007f
+#define  DEV_INT_SETCFG			0x00000001
+#define  DEV_INT_SETINTF		0x00000002
+#define  DEV_INT_INACTIVE		0x00000004
+#define  DEV_INT_USBRESET		0x00000008
+#define  DEV_INT_SUSPUSB		0x00000010
+#define  DEV_INT_SOF			0x00000020
+#define  DEV_INT_ENUM			0x00000040
+
+/* Endpoint Interrupt Register definitions */
+
+#define  ENDP0_INT_CTRLIN		0x00000001
+#define  ENDP1_INT_BULKIN		0x00000002
+#define  ENDP_INT_NONISOIN_MSK		0x0000AAAA
+#define  ENDP2_INT_BULKIN		0x00000004
+#define  ENDP0_INT_CTRLOUT		0x00010000
+#define  ENDP1_INT_BULKOUT		0x00020000
+#define  ENDP2_INT_BULKOUT		0x00040000
+#define  ENDP_INT_NONISOOUT_MSK		0x55540000
+
+/* Endpoint Register definitions */
+#define  ENDP_EPDIR_OUT			0x00000000
+#define  ENDP_EPDIR_IN			0x00000010
+#define  ENDP_EPTYPE_CNTL		0x0
+#define  ENDP_EPTYPE_ISO		0x1
+#define  ENDP_EPTYPE_BULK		0x2
+#define  ENDP_EPTYPE_INT		0x3
+
+/*
+ * Defines for Plug Detect
+ */
+
+struct plug_regs {
+	u32 plug_state;
+	u32 plug_pending;
+};
+
+/* Plug State Register definitions */
+#define  PLUG_STATUS_EN			0x1
+#define  PLUG_STATUS_ATTACHED		0x2
+#define  PLUG_STATUS_PHY_RESET		0x4
+#define  PLUG_STATUS_PHY_MODE		0x8
+
+/*
+ * Defines for UDC FIFO (Slave Mode)
+ */
+struct udcfifo_regs {
+	u32 *fifo_p;
+};
+
+/*
+ * USBTTY definitions
+ */
+#define  EP0_MAX_PACKET_SIZE        64
+#define  UDC_INT_ENDPOINT           1
+#define  UDC_INT_PACKET_SIZE        64
+#define  UDC_OUT_ENDPOINT           2
+#define  UDC_BULK_PACKET_SIZE       64
+#define  UDC_IN_ENDPOINT            3
+#define  UDC_OUT_PACKET_SIZE        64
+#define  UDC_IN_PACKET_SIZE         64

ws
change leading spaces to tabs
+
+/*
+ * Function declarations
+ */
+
+void udc_irq(void);
+
+void udc_set_nak(int epid);
+void udc_unset_nak(int epid);
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+int udc_init(void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
ws
could remove the extra empty line
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep,
+		  struct usb_endpoint_instance *endpoint);

Tom

             reply	other threads:[~2010-01-13 13:18 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-01-13 13:18 Tom [this message]
     [not found] ` <83d1d72b1001140300gd0c9f7dq3a50d45948dd9c76@mail.gmail.com>
2010-01-14 15:34   ` [U-Boot] [PATCH v4 06/12] SPEAr : usbd driver support for SPEAr SoCs Tom
  -- strict thread matches above, loose matches on Subject: below --
2010-01-11 11:15 [U-Boot] [PATCH v4 00/12] Support " Vipin KUMAR
2010-01-11 11:15 ` [U-Boot] [PATCH v4 01/12] SPEAr : Adding README.spear in doc Vipin KUMAR
2010-01-11 11:15   ` [U-Boot] [PATCH v4 02/12] SPEAr : Adding basic SPEAr architecture support Vipin KUMAR
2010-01-11 11:15     ` [U-Boot] [PATCH v4 03/12] SPEAr : i2c driver support added for SPEAr SoCs Vipin KUMAR
2010-01-11 11:15       ` [U-Boot] [PATCH v4 04/12] SPEAr : smi driver support " Vipin KUMAR
2010-01-11 11:15         ` [U-Boot] [PATCH v4 05/12] SPEAr : nand " Vipin KUMAR
2010-01-11 11:15           ` [U-Boot] [PATCH v4 06/12] SPEAr : usbd " Vipin KUMAR

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B4DC836.5050509@windriver.com \
    --to=tom.rix@windriver.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.