All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] V2 of OMAP3 USB device Support
@ 2009-09-28 16:34 y at windriver.com
  2009-09-28 16:34 ` [U-Boot] [PATCH 1/8] USB Consolidate descriptor definitions y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:34 UTC (permalink / raw)
  To: u-boot


The technical change is better handling of address setting on the
usb handshaking setup phase. 

Other changes from Jean's comments

2/8 USB add macros for debugging usb device setup.

static inline function replacing debug macros

3/8 TWL4030 Add usb PHY support

add empty lines between variables and statements
other empty lines added for readablity

4/8 OMAP3 Add usb device support

80+ char lines reduced
Used MUSB_FLAGS_PRINT macro suggestion
lowercased function names
multi-lined ep0_state_enum
Used suggestion on udelay to 1000 * 1000 
add empty lines between variables and statements
inverted check of ep0_urb->device_request.wLength
other empty lines added for readablity

5/8 OMAP3 zoom1 Add usbtty configuration

This was ack-ed by Jean

6/8 OMAP3 beagle Add usbtty configuration

This was ack-ed by Jean

8/8 OMAP3 zoom2 Use usbtty if the debug board

cleanup using usbtty_* functions or their stubs without #define's

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 1/8] USB Consolidate descriptor definitions
  2009-09-28 16:34 [U-Boot] V2 of OMAP3 USB device Support y at windriver.com
@ 2009-09-28 16:34 ` y at windriver.com
  2009-09-28 16:34   ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:34 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

The header files usb.h and usbdescriptors.h have the same or
similarly named structure definitions for

usb_device_descriptor
usb_string_descriptor
usb_endpoint_descriptor
usb_config_descriptor vs usb_configuration_descriptor
usb_interface_descriptor

There should only be one definition of these structures.
Some of these structures are element-wise duplicates,
one has unused elements that can be reduced to a duplicate,
and some of the the structures have additional elements.

These are the element-wise duplicates in usb.h

usb_device_descriptor
usb_string_descriptor

For these, the usb.h definition will be removed.

This definition in usb.h has extra unused elements

usb_endpoint_descriptor

	unsigned char	bRefresh
	unsigned char	bSynchAddress;

The definition of usb_endpoint_descriptor in usb.h will
be removed.

These definitions in usb.h have extra elements at the end of
the usb 2.0 specified descriptor:

usb_config_descriptor
usb_interface_descriptor

These structures will have their name shorted by removing the
'_descriptor' suffix.

So

usb_config_descriptor -> usb_config
usb_interface_descriptor -> usb_interface

The common descriptor elements are now defined by the macros

USB_CONFIG_DESCRIPTOR_DEFINITION
USB_INTERFACE_DESCRIPTOR_DEFINITION

This has been compile tested on MAKEALL arm, ppc and mips.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 common/cmd_usb.c            |   12 ++++----
 common/usb.c                |    8 ++--
 common/usb_kbd.c            |    4 +-
 common/usb_storage.c        |    2 +-
 cpu/ppc4xx/usbdev.c         |    4 +-
 drivers/usb/host/ehci-hcd.c |    2 +-
 drivers/usb/musb/musb_hcd.c |    2 +-
 include/usb.h               |   70 +++++-------------------------------------
 include/usbdescriptors.h    |   40 ++++++++++++++----------
 9 files changed, 49 insertions(+), 95 deletions(-)

diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 7b8ee6b..6f3b095 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -187,14 +187,14 @@ void usb_display_desc(struct usb_device *dev)
 
 }
 
-void usb_display_conf_desc(struct usb_config_descriptor *config,
+void usb_display_conf_desc(struct usb_config *config,
 			   struct usb_device *dev)
 {
 	printf("   Configuration: %d\n", config->bConfigurationValue);
 	printf("   - Interfaces: %d %s%s%dmA\n", config->bNumInterfaces,
 	       (config->bmAttributes & 0x40) ? "Self Powered " : "Bus Powered ",
 	       (config->bmAttributes & 0x20) ? "Remote Wakeup " : "",
-		config->MaxPower*2);
+		config->bMaxPower*2);
 	if (config->iConfiguration) {
 		printf("   - ");
 		usb_display_string(dev, config->iConfiguration);
@@ -202,7 +202,7 @@ void usb_display_conf_desc(struct usb_config_descriptor *config,
 	}
 }
 
-void usb_display_if_desc(struct usb_interface_descriptor *ifdesc,
+void usb_display_if_desc(struct usb_interface *ifdesc,
 			 struct usb_device *dev)
 {
 	printf("     Interface: %d\n", ifdesc->bInterfaceNumber);
@@ -246,8 +246,8 @@ void usb_display_ep_desc(struct usb_endpoint_descriptor *epdesc)
 /* main routine to diasplay the configs, interfaces and endpoints */
 void usb_display_config(struct usb_device *dev)
 {
-	struct usb_config_descriptor *config;
-	struct usb_interface_descriptor *ifdesc;
+	struct usb_config *config;
+	struct usb_interface *ifdesc;
 	struct usb_endpoint_descriptor *epdesc;
 	int i, ii;
 
@@ -321,7 +321,7 @@ void usb_show_tree_graph(struct usb_device *dev, char *pre)
 	printf(" %s (%s, %dmA)\n", usb_get_class_desc(
 					dev->config.if_desc[0].bInterfaceClass),
 					portspeed(dev->speed),
-					dev->config.MaxPower * 2);
+					dev->config.bMaxPower * 2);
 	if (strlen(dev->mf) || strlen(dev->prod) || strlen(dev->serial))
 		printf(" %s  %s %s %s\n", pre, dev->mf, dev->prod, dev->serial);
 	printf(" %s\n", pre);
diff --git a/common/usb.c b/common/usb.c
index 87fca70..6649f8c 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -440,10 +440,10 @@ int usb_get_configuration_no(struct usb_device *dev,
 {
 	int result;
 	unsigned int tmp;
-	struct usb_config_descriptor *config;
+	struct usb_config *config;
 
 
-	config = (struct usb_config_descriptor *)&buffer[0];
+	config = (struct usb_config *)&buffer[0];
 	result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
 	if (result < 9) {
 		if (result < 0)
@@ -489,7 +489,7 @@ int usb_set_address(struct usb_device *dev)
  */
 int usb_set_interface(struct usb_device *dev, int interface, int alternate)
 {
-	struct usb_interface_descriptor *if_face = NULL;
+	struct usb_interface *if_face = NULL;
 	int ret, i;
 
 	for (i = 0; i < dev->config.bNumInterfaces; i++) {
@@ -1347,7 +1347,7 @@ int usb_hub_configure(struct usb_device *dev)
 
 int usb_hub_probe(struct usb_device *dev, int ifnum)
 {
-	struct usb_interface_descriptor *iface;
+	struct usb_interface *iface;
 	struct usb_endpoint_descriptor *ep;
 	int ret;
 
diff --git a/common/usb_kbd.c b/common/usb_kbd.c
index b458d77..4e584a2 100644
--- a/common/usb_kbd.c
+++ b/common/usb_kbd.c
@@ -229,7 +229,7 @@ int usb_kbd_deregister(void)
 
 static void usb_kbd_setled(struct usb_device *dev)
 {
-	struct usb_interface_descriptor *iface;
+	struct usb_interface *iface;
 	iface = &dev->config.if_desc[0];
 	leds=0;
 	if(scroll_lock!=0)
@@ -348,7 +348,7 @@ static int usb_kbd_irq(struct usb_device *dev)
 /* probes the USB device dev for keyboard type */
 static int usb_kbd_probe(struct usb_device *dev, unsigned int ifnum)
 {
-	struct usb_interface_descriptor *iface;
+	struct usb_interface *iface;
 	struct usb_endpoint_descriptor *ep;
 	int pipe,maxp;
 
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 19613f2..4afc8ff 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -1070,7 +1070,7 @@ retry_it:
 int usb_storage_probe(struct usb_device *dev, unsigned int ifnum,
 		      struct us_data *ss)
 {
-	struct usb_interface_descriptor *iface;
+	struct usb_interface *iface;
 	int i;
 	unsigned int flags = 0;
 
diff --git a/cpu/ppc4xx/usbdev.c b/cpu/ppc4xx/usbdev.c
index 5bb4f3c..fe398af 100644
--- a/cpu/ppc4xx/usbdev.c
+++ b/cpu/ppc4xx/usbdev.c
@@ -21,7 +21,7 @@ void process_endpoints(unsigned short usb2d0_intrin)
 {
 	/*will hold the packet received */
 	struct usb_device_descriptor usb_device_packet;
-	struct usb_config_descriptor usb_config_packet;
+	struct usb_configuration_descriptor usb_config_packet;
 	struct usb_string_descriptor usb_string_packet;
 	struct devrequest setup_packet;
 	unsigned int *setup_packet_pt;
@@ -99,7 +99,7 @@ void process_endpoints(unsigned short usb2d0_intrin)
 				usb_config_packet.bConfigurationValue = 1;
 				usb_config_packet.iConfiguration = 0;
 				usb_config_packet.bmAttributes = 0x40;
-				usb_config_packet.MaxPower = 0;
+				usb_config_packet.bMaxPower = 0;
 
 				/*put packet in fifo */
 				packet_pt = (unsigned char *)&usb_config_packet;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index 324c308..ba85991 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -96,7 +96,7 @@ static struct descriptor {
 				 * UE_DIR_IN | EHCI_INTR_ENDPT
 				 */
 		3,		/* bmAttributes: UE_INTERRUPT */
-		8, 0,		/* wMaxPacketSize */
+		8,		/* wMaxPacketSize */
 		255		/* bInterval */
 	},
 };
diff --git a/drivers/usb/musb/musb_hcd.c b/drivers/usb/musb/musb_hcd.c
index 4ca94cb..555d2dc 100644
--- a/drivers/usb/musb/musb_hcd.c
+++ b/drivers/usb/musb/musb_hcd.c
@@ -803,7 +803,7 @@ void usb_event_poll()
 {
 	struct stdio_dev *dev;
 	struct usb_device *usb_kbd_dev;
-	struct usb_interface_descriptor *iface;
+	struct usb_interface *iface;
 	struct usb_endpoint_descriptor *ep;
 	int pipe;
 	int maxp;
diff --git a/include/usb.h b/include/usb.h
index 7c47098..378a23b 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -27,6 +27,7 @@
 #define _USB_H_
 
 #include <usb_defs.h>
+#include <usbdescriptors.h>
 
 /* Everything is aribtrary */
 #define USB_ALTSETTINGALLOC		4
@@ -41,13 +42,6 @@
 
 #define USB_CNTL_TIMEOUT 100 /* 100ms timeout */
 
-/* String descriptor */
-struct usb_string_descriptor {
-	unsigned char	bLength;
-	unsigned char	bDescriptorType;
-	unsigned short	wData[1];
-} __attribute__ ((packed));
-
 /* device request (setup) */
 struct devrequest {
 	unsigned char	requesttype;
@@ -63,47 +57,9 @@ struct usb_descriptor_header {
 	unsigned char	bDescriptorType;
 } __attribute__ ((packed));
 
-/* Device descriptor */
-struct usb_device_descriptor {
-	unsigned char	bLength;
-	unsigned char	bDescriptorType;
-	unsigned short	bcdUSB;
-	unsigned char	bDeviceClass;
-	unsigned char	bDeviceSubClass;
-	unsigned char	bDeviceProtocol;
-	unsigned char	bMaxPacketSize0;
-	unsigned short	idVendor;
-	unsigned short	idProduct;
-	unsigned short	bcdDevice;
-	unsigned char	iManufacturer;
-	unsigned char	iProduct;
-	unsigned char	iSerialNumber;
-	unsigned char	bNumConfigurations;
-} __attribute__ ((packed));
-
-/* Endpoint descriptor */
-struct usb_endpoint_descriptor {
-	unsigned char	bLength;
-	unsigned char	bDescriptorType;
-	unsigned char	bEndpointAddress;
-	unsigned char	bmAttributes;
-	unsigned short	wMaxPacketSize;
-	unsigned char	bInterval;
-	unsigned char	bRefresh;
-	unsigned char	bSynchAddress;
-} __attribute__ ((packed)) __attribute__ ((aligned(2)));
-
-/* Interface descriptor */
-struct usb_interface_descriptor {
-	unsigned char	bLength;
-	unsigned char	bDescriptorType;
-	unsigned char	bInterfaceNumber;
-	unsigned char	bAlternateSetting;
-	unsigned char	bNumEndpoints;
-	unsigned char	bInterfaceClass;
-	unsigned char	bInterfaceSubClass;
-	unsigned char	bInterfaceProtocol;
-	unsigned char	iInterface;
+/* Interface */
+struct usb_interface {
+	USB_INTERFACE_DESCRIPTOR_DEFINITION;
 
 	unsigned char	no_of_ep;
 	unsigned char	num_altsetting;
@@ -112,20 +68,12 @@ struct usb_interface_descriptor {
 	struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS];
 } __attribute__ ((packed));
 
-
-/* Configuration descriptor information.. */
-struct usb_config_descriptor {
-	unsigned char	bLength;
-	unsigned char	bDescriptorType;
-	unsigned short	wTotalLength;
-	unsigned char	bNumInterfaces;
-	unsigned char	bConfigurationValue;
-	unsigned char	iConfiguration;
-	unsigned char	bmAttributes;
-	unsigned char	MaxPower;
+/* Configuration information.. */
+struct usb_config {
+	USB_CONFIG_DESCRIPTOR_DEFINITION;
 
 	unsigned char	no_of_if;	/* number of interfaces */
-	struct usb_interface_descriptor if_desc[USB_MAXINTERFACES];
+	struct usb_interface if_desc[USB_MAXINTERFACES];
 } __attribute__ ((packed));
 
 enum {
@@ -156,7 +104,7 @@ struct usb_device {
 
 	int configno;			/* selected config number */
 	struct usb_device_descriptor descriptor; /* Device Descriptor */
-	struct usb_config_descriptor config; /* config descriptor */
+	struct usb_config config; /* config descriptor */
 
 	int have_langid;		/* whether string_langid is valid yet */
 	int string_langid;		/* language ID for strings */
diff --git a/include/usbdescriptors.h b/include/usbdescriptors.h
index a752097..ea05672 100644
--- a/include/usbdescriptors.h
+++ b/include/usbdescriptors.h
@@ -201,27 +201,33 @@ struct usb_endpoint_descriptor {
 	u8 bInterval;
 } __attribute__ ((packed));
 
+#define USB_INTERFACE_DESCRIPTOR_DEFINITION	\
+	u8 bLength;				\
+	u8 bDescriptorType;	/* 0x04 */	\
+	u8 bInterfaceNumber;			\
+	u8 bAlternateSetting;			\
+	u8 bNumEndpoints;			\
+	u8 bInterfaceClass;			\
+	u8 bInterfaceSubClass;			\
+	u8 bInterfaceProtocol;			\
+	u8 iInterface
+
 struct usb_interface_descriptor {
-	u8 bLength;
-	u8 bDescriptorType;	/* 0x04 */
-	u8 bInterfaceNumber;
-	u8 bAlternateSetting;
-	u8 bNumEndpoints;
-	u8 bInterfaceClass;
-	u8 bInterfaceSubClass;
-	u8 bInterfaceProtocol;
-	u8 iInterface;
+	USB_INTERFACE_DESCRIPTOR_DEFINITION;
 } __attribute__ ((packed));
 
+#define USB_CONFIG_DESCRIPTOR_DEFINITION \
+	u8 bLength;				\
+	u8 bDescriptorType;	/* 0x2 */	\
+	u16 wTotalLength;			\
+	u8 bNumInterfaces;			\
+	u8 bConfigurationValue;			\
+	u8 iConfiguration;			\
+	u8 bmAttributes;			\
+	u8 bMaxPower
+
 struct usb_configuration_descriptor {
-	u8 bLength;
-	u8 bDescriptorType;	/* 0x2 */
-	u16 wTotalLength;
-	u8 bNumInterfaces;
-	u8 bConfigurationValue;
-	u8 iConfiguration;
-	u8 bmAttributes;
-	u8 bMaxPower;
+	USB_CONFIG_DESCRIPTOR_DEFINITION;
 } __attribute__ ((packed));
 
 struct usb_device_descriptor {
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup.
  2009-09-28 16:34 ` [U-Boot] [PATCH 1/8] USB Consolidate descriptor definitions y at windriver.com
@ 2009-09-28 16:34   ` y at windriver.com
  2009-09-28 16:34     ` [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:34 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

When developing usb device features, it is useful to print out
common usb structures.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 include/usbdescriptors.h |   26 ++++++++++++
 include/usbdevice.h      |  103 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 129 insertions(+), 0 deletions(-)

diff --git a/include/usbdescriptors.h b/include/usbdescriptors.h
index ea05672..2d0b059 100644
--- a/include/usbdescriptors.h
+++ b/include/usbdescriptors.h
@@ -510,4 +510,30 @@ struct usb_class_descriptor {
 
 } __attribute__ ((packed));
 
+#ifdef DEBUG
+static inline void print_device_descriptor(struct usb_device_descriptor *d)
+{
+	serial_printf("usb device descriptor \n");
+	serial_printf("\tbLength %2.2x\n", d->bLength);
+	serial_printf("\tbDescriptorType %2.2x\n", d->bDescriptorType);
+	serial_printf("\tbcdUSB %4.4x\n", d->bcdUSB);
+	serial_printf("\tbDeviceClass %2.2x\n", d->bDeviceClass);
+	serial_printf("\tbDeviceSubClass %2.2x\n", d->bDeviceSubClass);
+	serial_printf("\tbDeviceProtocol %2.2x\n", d->bDeviceProtocol);
+	serial_printf("\tbMaxPacketSize0 %2.2x\n", d->bMaxPacketSize0);
+	serial_printf("\tidVendor %4.4x\n", d->idVendor);
+	serial_printf("\tidProduct %4.4x\n", d->idProduct);
+	serial_printf("\tbcdDevice %4.4x\n", d->bcdDevice);
+	serial_printf("\tiManufacturer %2.2x\n", d->iManufacturer);
+	serial_printf("\tiProduct %2.2x\n", d->iProduct);
+	serial_printf("\tiSerialNumber %2.2x\n", d->iSerialNumber);
+	serial_printf("\tbNumConfigurations %2.2x\n", d->bNumConfigurations);
+}
+
+#else
+
+/* stubs */
+#define print_device_descriptor(d)
+
+#endif /* DEBUG */
 #endif
diff --git a/include/usbdevice.h b/include/usbdevice.h
index 206dbbc..4171636 100644
--- a/include/usbdevice.h
+++ b/include/usbdevice.h
@@ -663,4 +663,107 @@ int usbd_endpoint_halted (struct usb_device_instance *device, int endpoint);
 void usbd_rcv_complete(struct usb_endpoint_instance *endpoint, int len, int urb_bad);
 void usbd_tx_complete (struct usb_endpoint_instance *endpoint);
 
+/* These are macros used in debugging */
+#ifdef DEBUG
+static inline void print_urb(struct urb *u)
+{
+	serial_printf("urb %p\n", (u));
+	serial_printf("\tendpoint %p\n", u->endpoint);
+	serial_printf("\tdevice %p\n", u->device);
+	serial_printf("\tbuffer %p\n", u->buffer);
+	serial_printf("\tbuffer_length %d\n", u->buffer_length);
+	serial_printf("\tactual_length %d\n", u->actual_length);
+	serial_printf("\tstatus %d\n", u->status);
+	serial_printf("\tdata %d\n", u->data);
+}
+
+static inline void print_usb_device_request(struct usb_device_request *r)
+{
+	serial_printf("usb request\n");
+	serial_printf("\tbmRequestType 0x%2.2x\n", r->bmRequestType);
+	if ((r->bmRequestType & USB_REQ_DIRECTION_MASK) == 0)
+		serial_printf("\t\tDirection : To device\n");
+	else
+		serial_printf("\t\tDirection : To host\n");
+	if ((r->bmRequestType & USB_TYPE_STANDARD) == USB_TYPE_STANDARD)
+		serial_printf("\t\tType      : Standard\n");
+	if ((r->bmRequestType & USB_TYPE_CLASS) == USB_TYPE_CLASS)
+		serial_printf("\t\tType      : Standard\n");
+	if ((r->bmRequestType & USB_TYPE_VENDOR) == USB_TYPE_VENDOR)
+		serial_printf("\t\tType      : Standard\n");
+	if ((r->bmRequestType & USB_TYPE_RESERVED) == USB_TYPE_RESERVED)
+		serial_printf("\t\tType      : Standard\n");
+	if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
+	    USB_REQ_RECIPIENT_DEVICE)
+		serial_printf("\t\tRecipient : Device\n");
+	if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
+	    USB_REQ_RECIPIENT_INTERFACE)
+		serial_printf("\t\tRecipient : Interface\n");
+	if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
+	    USB_REQ_RECIPIENT_ENDPOINT)
+		serial_printf("\t\tRecipient : Endpoint\n");
+	if ((r->bmRequestType & USB_REQ_RECIPIENT_MASK) ==
+	    USB_REQ_RECIPIENT_OTHER)
+		serial_printf("\t\tRecipient : Other\n");
+	serial_printf("\tbRequest      0x%2.2x\n", r->bRequest);
+	if (r->bRequest == USB_REQ_GET_STATUS)
+		serial_printf("\t\tGET_STATUS\n");
+	else if (r->bRequest == USB_REQ_SET_ADDRESS)
+		serial_printf("\t\tSET_ADDRESS\n");
+	else if (r->bRequest == USB_REQ_SET_FEATURE)
+		serial_printf("\t\tSET_FEATURE\n");
+	else if (r->bRequest == USB_REQ_GET_DESCRIPTOR)
+		serial_printf("\t\tGET_DESCRIPTOR\n");
+	else if (r->bRequest == USB_REQ_SET_CONFIGURATION)
+		serial_printf("\t\tSET_CONFIGURATION\n");
+	else if (r->bRequest == USB_REQ_SET_INTERFACE)
+		serial_printf("\t\tUSB_REQ_SET_INTERFACE\n");
+	else
+		serial_printf("\tUNKNOWN %d\n", r->bRequest);
+	serial_printf("\twValue        0x%4.4x\n", r->wValue);
+	if (r->bRequest == USB_REQ_GET_DESCRIPTOR) {
+		switch (r->wValue >> 8) {
+		case USB_DESCRIPTOR_TYPE_DEVICE:
+			serial_printf("\tDEVICE\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+			serial_printf("\tCONFIGURATION\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_STRING:
+			serial_printf("\tSTRING\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_INTERFACE:
+			serial_printf("\tINTERFACE\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_ENDPOINT:
+			serial_printf("\tENDPOINT\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
+			serial_printf("\tDEVICE_QUALIFIER\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
+			serial_printf("\tOTHER_SPEED_CONFIGURATION\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_INTERFACE_POWER:
+			serial_printf("\tINTERFACE_POWER\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_HID:
+			serial_printf("\tHID\n");
+			break;
+		case USB_DESCRIPTOR_TYPE_REPORT:
+			serial_printf("\tREPORT\n");
+			break;
+		default:
+			serial_printf("\tUNKNOWN TYPE\n");
+			break;
+		}
+	}
+	serial_printf("\twIndex        0x%4.4x\n", r->wIndex);
+	serial_printf("\twLength       0x%4.4x\n", r->wLength);
+}
+#else
+/* stubs */
+#define print_urb(u)
+#define print_usb_device_request(r)
+#endif /* DEBUG */
 #endif
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support
  2009-09-28 16:34   ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup y at windriver.com
@ 2009-09-28 16:34     ` y at windriver.com
  2009-09-28 16:34       ` [U-Boot] [PATCH 4/8] OMAP3 Add usb device support y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:34 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

The twl4030 provides a PHY device for connecting a link device,
like musb, to physical connection.

This change adds the twl4030 usb registers and functions for
initializing the PHY as required by omap3.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 Makefile                  |    1 +
 drivers/usb/phy/Makefile  |   44 +++++++++++
 drivers/usb/phy/twl4030.c |  189 +++++++++++++++++++++++++++++++++++++++++++++
 include/twl4030.h         |  143 ++++++++++++++++++++++++++++++----
 4 files changed, 362 insertions(+), 15 deletions(-)
 create mode 100644 drivers/usb/phy/Makefile
 create mode 100644 drivers/usb/phy/twl4030.c

diff --git a/Makefile b/Makefile
index 356ca29..7ceb066 100644
--- a/Makefile
+++ b/Makefile
@@ -243,6 +243,7 @@ LIBS += drivers/twserial/libtws.a
 LIBS += drivers/usb/gadget/libusb_gadget.a
 LIBS += drivers/usb/host/libusb_host.a
 LIBS += drivers/usb/musb/libusb_musb.a
+LIBS += drivers/usb/phy/libusb_phy.a
 LIBS += drivers/video/libvideo.a
 LIBS += drivers/watchdog/libwatchdog.a
 LIBS += common/libcommon.a
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
new file mode 100644
index 0000000..200b907
--- /dev/null
+++ b/drivers/usb/phy/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2009 Wind River Systems, Inc.
+# Tom Rix <Tom.Rix@windriver.com>
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libusb_phy.a
+
+COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
+COBJS-y := twl4030.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c
new file mode 100644
index 0000000..54d2e61
--- /dev/null
+++ b/drivers/usb/phy/twl4030.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * This is file is based on
+ * repository git.gitorious.org/u-boot-omap3/mainline.git,
+ * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
+ *
+ * This is the unique part of its copyright :
+ *
+ * ------------------------------------------------------------------------
+ *
+ *  * (C) Copyright 2009 Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
+ * Copyright (C) 2004-2007 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * Author: Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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
+ */
+
+#include <twl4030.h>
+
+/* Defines for bits in registers */
+#define OPMODE_MASK		(3 << 3)
+#define XCVRSELECT_MASK		(3 << 0)
+#define CARKITMODE		(1 << 2)
+#define OTG_ENAB		(1 << 5)
+#define PHYPWD			(1 << 0)
+#define CLOCKGATING_EN		(1 << 2)
+#define CLK32K_EN		(1 << 1)
+#define REQ_PHY_DPLL_CLK	(1 << 0)
+#define PHY_DPLL_CLK		(1 << 0)
+
+static int twl4030_usb_write(u8 address, u8 data)
+{
+	int ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, data, address);
+	if (ret != 0)
+		printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
+
+	return ret;
+}
+
+static int twl4030_usb_read(u8 address)
+{
+	u8 data;
+	int ret;
+
+	ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, &data, address);
+	if (ret == 0)
+		ret = data;
+	else
+		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
+
+	return ret;
+}
+
+static void twl4030_usb_ldo_init(void)
+{
+	/* Enable writing to power configuration registers */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0xC0,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x0C,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+
+	/* put VUSB3V1 LDO in active state */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB_DEDICATED2);
+
+	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x14,
+			     TWL4030_PM_RECEIVER_VUSB_DEDICATED1);
+
+	/* turn on 3.1V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB3V1_TYPE);
+
+	/* turn on 1.5V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB1V5_TYPE);
+
+	/* turn on 1.8V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB1V8_TYPE);
+
+	/* disable access to power configuration registers */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x00,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+}
+
+static void twl4030_phy_power(void)
+{
+	u8 pwr, clk;
+
+	/* Power the PHY */
+	pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
+	pwr &= ~PHYPWD;
+	twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
+	/* Enable clocks */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk |= CLOCKGATING_EN | CLK32K_EN;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+}
+
+/*
+ * Initiaze the ULPI interface
+ * ULPI : Universal Transceiver Macrocell Low Pin Interface
+ * An interface between the USB link controller like musb and the
+ * the PHY or transceiver that drives the actual bus.
+ */
+int twl4030_usb_ulpi_init(void)
+{
+	long timeout = 1000 * 1000; /* 1 sec */;
+	u8 clk, sts, pwr;
+
+	/* twl4030 ldo init */
+	twl4030_usb_ldo_init();
+
+	/* Enable the twl4030 phy */
+	twl4030_phy_power();
+
+	/* Enable DPLL to access PHY registers over I2C */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk |= REQ_PHY_DPLL_CLK;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+
+	/* Check if the PHY DPLL is locked */
+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+	while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
+		udelay(10);
+		sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+		timeout -= 10;
+	}
+
+	/* Final check */
+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+	if (!(sts & PHY_DPLL_CLK)) {
+		printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
+		return -1;
+	}
+
+	/*
+	 * There are two circuit blocks attached to the PHY,
+	 * Carkit and USB OTG.  Disable Carkit and enable USB OTG
+	 */
+	twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
+	pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
+	pwr |= OTG_ENAB;
+	twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
+
+	/* Clear the opmode bits to ensure normal encode */
+	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
+
+	/* Clear the xcvrselect bits to enable the high speed transeiver */
+	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
+
+	/* Let ULPI control the DPLL clock */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk &= ~REQ_PHY_DPLL_CLK;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+
+	return 0;
+}
diff --git a/include/twl4030.h b/include/twl4030.h
index f260ecb..feaec47 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -342,21 +342,129 @@
 #define TWL4030_KEYPAD_CTRL_SOFT_NRST			(1 << 0)
 
 /* USB */
-#define TWL4030_USB_FUNC_CTRL				(0x04)
-#define TWL4030_USB_OPMODE_MASK				(3 << 3)
-#define TWL4030_USB_XCVRSELECT_MASK			(3 << 0)
-#define TWL4030_USB_IFC_CTRL				(0x07)
-#define TWL4030_USB_CARKITMODE				(1 << 2)
-#define TWL4030_USB_POWER_CTRL				(0xAC)
-#define TWL4030_USB_OTG_ENAB				(1 << 5)
-#define TWL4030_USB_PHY_PWR_CTRL			(0xFD)
-#define TWL4030_USB_PHYPWD				(1 << 0)
-#define TWL4030_USB_PHY_CLK_CTRL			(0xFE)
-#define TWL4030_USB_CLOCKGATING_EN			(1 << 2)
-#define TWL4030_USB_CLK32K_EN				(1 << 1)
-#define TWL4030_USB_REQ_PHY_DPLL_CLK			(1 << 0)
-#define TWL4030_USB_PHY_CLK_CTRL_STS			(0xFF)
-#define TWL4030_USB_PHY_DPLL_CLK			(1 << 0)
+#define TWL4030_USB_VENDOR_ID_LO			0x00
+#define TWL4030_USB_VENDOR_ID_HI			0x01
+#define TWL4030_USB_PRODUCT_ID_LO			0x02
+#define TWL4030_USB_PRODUCT_ID_HI			0x03
+#define TWL4030_USB_FUNC_CTRL				0x04
+#define TWL4030_USB_FUNC_CTRL_SET			0x05
+#define TWL4030_USB_FUNC_CTRL_CLR			0x06
+#define TWL4030_USB_IFC_CTRL				0x07
+#define TWL4030_USB_IFC_CTRL_SET			0x08
+#define TWL4030_USB_IFC_CTRL_CLR			0x09
+#define TWL4030_USB_OTG_CTRL				0x0A
+#define TWL4030_USB_OTG_CTRL_SET			0x0B
+#define TWL4030_USB_OTG_CTRL_CLR			0x0C
+#define TWL4030_USB_USB_INT_EN_RISE			0x0D
+#define TWL4030_USB_USB_INT_EN_RISE_SET			0x0E
+#define TWL4030_USB_USB_INT_EN_RISE_CLR			0x0F
+#define TWL4030_USB_USB_INT_EN_FALL			0x10
+#define TWL4030_USB_USB_INT_EN_FALL_SET			0x11
+#define TWL4030_USB_USB_INT_EN_FALL_CLR			0x12
+#define TWL4030_USB_USB_INT_STS				0x13
+#define TWL4030_USB_USB_INT_LATCH			0x14
+#define TWL4030_USB_DEBUG				0x15
+#define TWL4030_USB_SCRATCH_REG				0x16
+#define TWL4030_USB_SCRATCH_REG_SET			0x17
+#define TWL4030_USB_SCRATCH_REG_CLR			0x18
+#define TWL4030_USB_CARKIT_CTRL				0x19
+#define TWL4030_USB_CARKIT_CTRL_SET			0x1A
+#define TWL4030_USB_CARKIT_CTRL_CLR			0x1B
+#define TWL4030_USB_CARKIT_INT_DELAY			0x1C
+#define TWL4030_USB_CARKIT_INT_EN			0x1D
+#define TWL4030_USB_CARKIT_INT_EN_SET			0x1E
+#define TWL4030_USB_CARKIT_INT_EN_CLR			0x1F
+#define TWL4030_USB_CARKIT_INT_STS			0x20
+#define TWL4030_USB_CARKIT_INT_LATCH			0x21
+#define TWL4030_USB_CARKIT_PLS_CTRL			0x22
+#define TWL4030_USB_CARKIT_PLS_CTRL_SET			0x23
+#define TWL4030_USB_CARKIT_PLS_CTRL_CLR			0x24
+#define TWL4030_USB_TRANS_POS_WIDTH			0x25
+#define TWL4030_USB_TRANS_NEG_WIDTH			0x26
+#define TWL4030_USB_RCV_PLTY_RECOVERY			0x27
+#define TWL4030_USB_MCPC_CTRL				0x30
+#define TWL4030_USB_MCPC_CTRL_SET			0x31
+#define TWL4030_USB_MCPC_CTRL_CLR			0x32
+#define TWL4030_USB_MCPC_IO_CTRL			0x33
+#define TWL4030_USB_MCPC_IO_CTRL_SET			0x34
+#define TWL4030_USB_MCPC_IO_CTRL_CLR			0x35
+#define TWL4030_USB_MCPC_CTRL2				0x36
+#define TWL4030_USB_MCPC_CTRL2_SET			0x37
+#define TWL4030_USB_MCPC_CTRL2_CLR			0x38
+#define TWL4030_USB_OTHER_FUNC_CTRL			0x80
+#define TWL4030_USB_OTHER_FUNC_CTRL_SET			0x81
+#define TWL4030_USB_OTHER_FUNC_CTRL_CLR			0x82
+#define TWL4030_USB_OTHER_IFC_CTRL			0x83
+#define TWL4030_USB_OTHER_IFC_CTRL_SET			0x84
+#define TWL4030_USB_OTHER_IFC_CTRL_CLR			0x85
+#define TWL4030_USB_OTHER_INT_EN_RISE_SET		0x87
+#define TWL4030_USB_OTHER_INT_EN_RISE_CLR		0x88
+#define TWL4030_USB_OTHER_INT_EN_FALL			0x89
+#define TWL4030_USB_OTHER_INT_EN_FALL_SET		0x8A
+#define TWL4030_USB_OTHER_INT_EN_FALL_CLR		0x8B
+#define TWL4030_USB_OTHER_INT_STS			0x8C
+#define TWL4030_USB_OTHER_INT_LATCH			0x8D
+#define TWL4030_USB_ID_STATUS				0x96
+#define TWL4030_USB_CARKIT_SM_1_INT_EN			0x97
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_SET		0x98
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_CLR		0x99
+#define TWL4030_USB_CARKIT_SM_1_INT_STS			0x9A
+#define TWL4030_USB_CARKIT_SM_1_INT_LATCH		0x9B
+#define TWL4030_USB_CARKIT_SM_2_INT_EN			0x9C
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_SET		0x9D
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_CLR		0x9E
+#define TWL4030_USB_CARKIT_SM_2_INT_STS			0x9F
+#define TWL4030_USB_CARKIT_SM_2_INT_LATCH		0xA0
+#define TWL4030_USB_CARKIT_SM_CTRL			0xA1
+#define TWL4030_USB_CARKIT_SM_CTRL_SET			0xA2
+#define TWL4030_USB_CARKIT_SM_CTRL_CLR			0xA3
+#define TWL4030_USB_CARKIT_SM_CMD			0xA4
+#define TWL4030_USB_CARKIT_SM_CMD_SET			0xA5
+#define TWL4030_USB_CARKIT_SM_CMD_CLR			0xA6
+#define TWL4030_USB_CARKIT_SM_CMD_STS			0xA7
+#define TWL4030_USB_CARKIT_SM_STATUS			0xA8
+#define TWL4030_USB_CARKIT_SM_ERR_STATUS		0xAA
+#define TWL4030_USB_CARKIT_SM_CTRL_STATE		0xAB
+#define TWL4030_USB_POWER_CTRL				0xAC
+#define TWL4030_USB_POWER_CTRL_SET			0xAD
+#define TWL4030_USB_POWER_CTRL_CLR			0xAE
+#define TWL4030_USB_OTHER_IFC_CTRL2			0xAF
+#define TWL4030_USB_OTHER_IFC_CTRL2_SET			0xB0
+#define TWL4030_USB_OTHER_IFC_CTRL2_CLR			0xB1
+#define TWL4030_USB_REG_CTRL_EN				0xB2
+#define TWL4030_USB_REG_CTRL_EN_SET			0xB3
+#define TWL4030_USB_REG_CTRL_EN_CLR			0xB4
+#define TWL4030_USB_REG_CTRL_ERROR			0xB5
+#define TWL4030_USB_OTHER_FUNC_CTRL2			0xB8
+#define TWL4030_USB_OTHER_FUNC_CTRL2_SET		0xB9
+#define TWL4030_USB_OTHER_FUNC_CTRL2_CLR		0xBA
+#define TWL4030_USB_CARKIT_ANA_CTRL			0xBB
+#define TWL4030_USB_CARKIT_ANA_CTRL_SET			0xBC
+#define TWL4030_USB_CARKIT_ANA_CTRL_CLR			0xBD
+#define TWL4030_USB_VBUS_DEBOUNCE			0xC0
+#define TWL4030_USB_ID_DEBOUNCE				0xC1
+#define TWL4030_USB_TPH_DP_CON_MIN			0xC2
+#define TWL4030_USB_TPH_DP_CON_MAX			0xC3
+#define TWL4030_USB_TCR_DP_CON_MIN			0xC4
+#define TWL4030_USB_TCR_DP_CON_MAX			0xC5
+#define TWL4030_USB_TPH_DP_PD_SHORT			0xC6
+#define TWL4030_USB_TPH_CMD_DLY				0xC7
+#define TWL4030_USB_TPH_DET_RST				0xC8
+#define TWL4030_USB_TPH_AUD_BIAS			0xC9
+#define TWL4030_USB_TCR_UART_DET_MIN			0xCA
+#define TWL4030_USB_TCR_UART_DET_MAX			0xCB
+#define TWL4030_USB_TPH_ID_INT_PW			0xCD
+#define TWL4030_USB_TACC_ID_INT_WAIT			0xCE
+#define TWL4030_USB_TACC_ID_INT_PW			0xCF
+#define TWL4030_USB_TPH_CMD_WAIT			0xD0
+#define TWL4030_USB_TPH_ACK_WAIT			0xD1
+#define TWL4030_USB_TPH_DP_DISC_DET			0xD2
+#define TWL4030_USB_VBAT_TIMER				0xD3
+#define TWL4030_USB_CARKIT_4W_DEBUG			0xE0
+#define TWL4030_USB_CARKIT_5W_DEBUG			0xE1
+#define TWL4030_USB_PHY_PWR_CTRL			0xFD
+#define TWL4030_USB_PHY_CLK_CTRL			0xFE
+#define TWL4030_USB_PHY_CLK_CTRL_STS			0xFF
 
 /*
  * Convience functions to read and write from TWL4030
@@ -398,4 +506,9 @@ void twl4030_power_mmc_init(void);
  */
 void twl4030_led_init(void);
 
+/*
+ * USB
+ */
+int twl4030_usb_ulpi_init(void);
+
 #endif /* TWL4030_H */
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 4/8] OMAP3 Add usb device support
  2009-09-28 16:34     ` [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support y at windriver.com
@ 2009-09-28 16:34       ` y at windriver.com
  2009-09-28 16:35         ` [U-Boot] [PATCH 5/8] OMAP3 zoom1 Add usbtty configuration y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:34 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

This change adds the usb device support for musb.

Omap3 platform support added at the same level as davinci.

The interface for usbtty to use the musb device support was added.

Verified on omap3 beagle, zoom1 and zoom2.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 drivers/serial/usbtty.h       |    2 +
 drivers/usb/musb/Makefile     |    2 +
 drivers/usb/musb/musb_core.c  |    8 +-
 drivers/usb/musb/musb_core.h  |   40 ++
 drivers/usb/musb/musb_debug.h |  205 +++++++++
 drivers/usb/musb/musb_udc.c   |  963 +++++++++++++++++++++++++++++++++++++++++
 drivers/usb/musb/omap3.c      |  129 ++++++
 drivers/usb/musb/omap3.h      |   48 ++
 include/usb.h                 |    3 +-
 include/usb/musb_udc.h        |   54 +++
 10 files changed, 1451 insertions(+), 3 deletions(-)
 create mode 100644 drivers/usb/musb/musb_debug.h
 create mode 100644 drivers/usb/musb/musb_udc.c
 create mode 100644 drivers/usb/musb/omap3.c
 create mode 100644 drivers/usb/musb/omap3.h
 create mode 100644 include/usb/musb_udc.h

diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h
index f746d63..6b6c4a1 100644
--- a/drivers/serial/usbtty.h
+++ b/drivers/serial/usbtty.h
@@ -29,6 +29,8 @@
 #include <usb/mpc8xx_udc.h>
 #elif defined(CONFIG_OMAP1510)
 #include <usb/omap1510_udc.h>
+#elif defined(CONFIG_MUSB_UDC)
+#include <usb/musb_udc.h>
 #elif defined(CONFIG_PXA27X)
 #include <usb/pxa27x_udc.h>
 #endif
diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile
index 09e0a5f..f2ccd9f 100644
--- a/drivers/usb/musb/Makefile
+++ b/drivers/usb/musb/Makefile
@@ -26,7 +26,9 @@ include $(TOPDIR)/config.mk
 LIB	:= $(obj)libusb_musb.a
 
 COBJS-$(CONFIG_MUSB_HCD) += musb_hcd.o musb_core.o
+COBJS-$(CONFIG_MUSB_UDC) += musb_udc.o musb_core.o
 COBJS-$(CONFIG_USB_DAVINCI) += davinci.o
+COBJS-$(CONFIG_USB_OMAP3) += omap3.o
 
 COBJS	:= $(COBJS-y)
 SRCS	:= $(COBJS:.o=.c)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index ec57fc8..22f3dba 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -32,7 +32,9 @@ struct musb_regs *musbr;
  */
 void musb_start(void)
 {
+#if defined(CONFIG_MUSB_HCD)
 	u8 devctl;
+#endif
 
 	/* disable all interrupts */
 	writew(0, &musbr->intrtxe);
@@ -74,9 +76,10 @@ void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
 			/* Configure fifo size and fifo base address */
 			writeb(idx, &musbr->txfifosz);
 			writew(fifoaddr >> 3, &musbr->txfifoadd);
+
+			csr = readw(&musbr->txcsr);
 #if defined(CONFIG_MUSB_HCD)
 			/* clear the data toggle bit */
-			csr = readw(&musbr->txcsr);
 			writew(csr | MUSB_TXCSR_CLRDATATOG, &musbr->txcsr);
 #endif
 			/* Flush fifo if required */
@@ -87,9 +90,10 @@ void musb_configure_ep(struct musb_epinfo *epinfo, u8 cnt)
 			/* Configure fifo size and fifo base address */
 			writeb(idx, &musbr->rxfifosz);
 			writew(fifoaddr >> 3, &musbr->rxfifoadd);
+
+			csr = readw(&musbr->rxcsr);
 #if defined(CONFIG_MUSB_HCD)
 			/* clear the data toggle bit */
-			csr = readw(&musbr->rxcsr);
 			writew(csr | MUSB_RXCSR_CLRDATATOG, &musbr->rxcsr);
 #endif
 			/* Flush fifo if required */
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index f9da3f0..15c7f49 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -40,6 +40,36 @@
 
 #define MUSB_EP0_FIFOSIZE	64	/* This is non-configurable */
 
+/* EP0 */
+struct musb_ep0_regs {
+	u16	reserved4;
+	u16	csr0;
+	u16	reserved5;
+	u16	reserved6;
+	u16	count0;
+	u8	host_type0;
+	u8	host_naklimit0;
+	u8	reserved7;
+	u8	reserved8;
+	u8	reserved9;
+	u8	configdata;
+};
+
+/* EP 1-15 */
+struct musb_epN_regs {
+	u16	txmaxp;
+	u16	txcsr;
+	u16	rxmaxp;
+	u16	rxcsr;
+	u16	rxcount;
+	u8	txtype;
+	u8	txinterval;
+	u8	rxtype;
+	u8	rxinterval;
+	u8	reserved0;
+	u8	fifosize;
+};
+
 /* Mentor USB core register overlay structure */
 struct musb_regs {
 	/* common registers */
@@ -97,6 +127,16 @@ struct musb_regs {
 		u8	rxhubaddr;
 		u8	rxhubport;
 	} tar[16];
+	/*
+	 * end point registers
+	 * ep0 elements are valid when array index is 0
+	 * otherwise epN is valid
+	 */
+	union musb_ep_regs {
+		struct musb_ep0_regs ep0;
+		struct musb_epN_regs epN;
+	} ep[16];
+
 } __attribute__((aligned(32)));
 
 /*
diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h
new file mode 100644
index 0000000..62380ff
--- /dev/null
+++ b/drivers/usb/musb/musb_debug.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * 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
+ */
+
+/* Define MUSB_DEBUG before including this file to get debug macros */
+#ifdef MUSB_DEBUG
+
+#define MUSB_FLAGS_PRINT(v, x, y)		\
+  if (((v) & MUSB_##x##_##y))			\
+		serial_printf("\t\t"#y"\n")
+
+static inline void musb_print_pwr(u8 b)
+{
+	serial_printf("\tpower   0x%2.2x\n", b);
+	MUSB_FLAGS_PRINT(b, POWER, ISOUPDATE);
+	MUSB_FLAGS_PRINT(b, POWER, SOFTCONN);
+	MUSB_FLAGS_PRINT(b, POWER, HSENAB);
+	MUSB_FLAGS_PRINT(b, POWER, HSMODE);
+	MUSB_FLAGS_PRINT(b, POWER, RESET);
+	MUSB_FLAGS_PRINT(b, POWER, RESUME);
+	MUSB_FLAGS_PRINT(b, POWER, SUSPENDM);
+	MUSB_FLAGS_PRINT(b, POWER, ENSUSPEND);
+}
+
+static inline void musb_print_csr0(u16 w)
+{
+	serial_printf("\tcsr0    0x%4.4x\n", w);
+	MUSB_FLAGS_PRINT(w, CSR0, FLUSHFIFO);
+	MUSB_FLAGS_PRINT(w, CSR0_P, SVDSETUPEND);
+	MUSB_FLAGS_PRINT(w, CSR0_P, SVDRXPKTRDY);
+	MUSB_FLAGS_PRINT(w, CSR0_P, SENDSTALL);
+	MUSB_FLAGS_PRINT(w, CSR0_P, SETUPEND);
+	MUSB_FLAGS_PRINT(w, CSR0_P, DATAEND);
+	MUSB_FLAGS_PRINT(w, CSR0_P, SENTSTALL);
+	MUSB_FLAGS_PRINT(w, CSR0, TXPKTRDY);
+	MUSB_FLAGS_PRINT(w, CSR0, RXPKTRDY);
+}
+
+static inline void musb_print_intrusb(u8 b)
+{
+	serial_printf("\tintrusb 0x%2.2x\n", b);
+	MUSB_FLAGS_PRINT(b, INTR, VBUSERROR);
+	MUSB_FLAGS_PRINT(b, INTR, SESSREQ);
+	MUSB_FLAGS_PRINT(b, INTR, DISCONNECT);
+	MUSB_FLAGS_PRINT(b, INTR, CONNECT);
+	MUSB_FLAGS_PRINT(b, INTR, SOF);
+	MUSB_FLAGS_PRINT(b, INTR, RESUME);
+	MUSB_FLAGS_PRINT(b, INTR, SUSPEND);
+
+	if (b & MUSB_INTR_BABBLE)
+		serial_printf("\t\tMUSB_INTR_RESET or MUSB_INTR_BABBLE\n");
+
+}
+
+static inline void musb_print_intrtx(u16 w)
+{
+	serial_printf("\tintrtx 0x%4.4x\n", w);
+}
+
+static inline void musb_print_intrrx(u16 w)
+{
+	serial_printf("\tintrx 0x%4.4x\n", w);
+}
+
+static inline void musb_print_devctl(u8 b)
+{
+	serial_printf("\tdevctl  0x%2.2x\n", b);
+	if (b & MUSB_DEVCTL_BDEVICE)
+		serial_printf("\t\tB device\n");
+	else
+		serial_printf("\t\tA device\n");
+	if (b & MUSB_DEVCTL_FSDEV)
+		serial_printf("\t\tFast Device -(host mode)\n");
+	if (b & MUSB_DEVCTL_LSDEV)
+		serial_printf("\t\tSlow Device -(host mode)\n");
+	if (b & MUSB_DEVCTL_HM)
+		serial_printf("\t\tHost mode\n");
+	else
+		serial_printf("\t\tPeripherial mode\n");
+	if (b & MUSB_DEVCTL_HR)
+		serial_printf("\t\tHost request started(B device)\n");
+	else
+		serial_printf("\t\tHost request finished(B device)\n");
+	if (b & MUSB_DEVCTL_BDEVICE) {
+		if (b & MUSB_DEVCTL_SESSION)
+			serial_printf("\t\tStart of session(B device)\n");
+		else
+			serial_printf("\t\tEnd of session(B device)\n");
+	} else {
+		if (b & MUSB_DEVCTL_SESSION)
+			serial_printf("\t\tStart of session(A device)\n");
+		else
+			serial_printf("\t\tEnd of session(A device)\n");
+	}
+}
+
+static inline void musb_print_config(u8 b)
+{
+	serial_printf("\tconfig 0x%2.2x\n", b);
+	if (b & MUSB_CONFIGDATA_MPRXE)
+		serial_printf("\t\tAuto combine rx bulk packets\n");
+	if (b & MUSB_CONFIGDATA_MPTXE)
+		serial_printf("\t\tAuto split tx bulk packets\n");
+	if (b & MUSB_CONFIGDATA_BIGENDIAN)
+		serial_printf("\t\tBig Endian ordering\n");
+	else
+		serial_printf("\t\tLittle Endian ordering\n");
+	if (b & MUSB_CONFIGDATA_HBRXE)
+		serial_printf("\t\tHigh speed rx iso endpoint\n");
+	if (b & MUSB_CONFIGDATA_HBTXE)
+		serial_printf("\t\tHigh speed tx iso endpoint\n");
+	if (b & MUSB_CONFIGDATA_DYNFIFO)
+		serial_printf("\t\tDynamic fifo sizing\n");
+	if (b & MUSB_CONFIGDATA_SOFTCONE)
+		serial_printf("\t\tSoft Connect\n");
+	if (b & MUSB_CONFIGDATA_UTMIDW)
+		serial_printf("\t\t16 bit data width\n");
+	else
+		serial_printf("\t\t8 bit data width\n");
+}
+
+static inline void musb_print_rxmaxp(u16 w)
+{
+	serial_printf("\trxmaxp  0x%4.4x\n", w);
+}
+
+static inline void musb_print_rxcsr(u16 w)
+{
+	serial_printf("\trxcsr   0x%4.4x\n", w);
+	MUSB_FLAGS_PRINT(w, RXCSR, AUTOCLEAR);
+	MUSB_FLAGS_PRINT(w, RXCSR, DMAENAB);
+	MUSB_FLAGS_PRINT(w, RXCSR, DISNYET);
+	MUSB_FLAGS_PRINT(w, RXCSR, PID_ERR);
+	MUSB_FLAGS_PRINT(w, RXCSR, DMAMODE);
+	MUSB_FLAGS_PRINT(w, RXCSR, CLRDATATOG);
+	MUSB_FLAGS_PRINT(w, RXCSR, FLUSHFIFO);
+	MUSB_FLAGS_PRINT(w, RXCSR, DATAERROR);
+	MUSB_FLAGS_PRINT(w, RXCSR, FIFOFULL);
+	MUSB_FLAGS_PRINT(w, RXCSR, RXPKTRDY);
+	MUSB_FLAGS_PRINT(w, RXCSR_P, SENTSTALL);
+	MUSB_FLAGS_PRINT(w, RXCSR_P, SENDSTALL);
+	MUSB_FLAGS_PRINT(w, RXCSR_P, OVERRUN);
+
+	if (w & MUSB_RXCSR_P_ISO)
+		serial_printf("\t\tiso mode\n");
+	else
+		serial_printf("\t\tbulk mode\n");
+
+}
+
+static inline void musb_print_txmaxp(u16 w)
+{
+	serial_printf("\ttxmaxp  0x%4.4x\n", w);
+}
+
+static inline void musb_print_txcsr(u16 w)
+{
+	serial_printf("\ttxcsr   0x%4.4x\n", w);
+	MUSB_FLAGS_PRINT(w, TXCSR, TXPKTRDY);
+	MUSB_FLAGS_PRINT(w, TXCSR, FIFONOTEMPTY);
+	MUSB_FLAGS_PRINT(w, TXCSR, FLUSHFIFO);
+	MUSB_FLAGS_PRINT(w, TXCSR, CLRDATATOG);
+	MUSB_FLAGS_PRINT(w, TXCSR_P, UNDERRUN);
+	MUSB_FLAGS_PRINT(w, TXCSR_P, SENTSTALL);
+	MUSB_FLAGS_PRINT(w, TXCSR_P, SENDSTALL);
+
+	if (w & MUSB_TXCSR_MODE)
+		serial_printf("\t\tTX mode\n");
+	else
+		serial_printf("\t\tRX mode\n");
+}
+
+#else
+
+/* stubs */
+
+#define musb_print_pwr(b)
+#define musb_print_csr0(w)
+#define musb_print_intrusb(b)
+#define musb_print_intrtx(w)
+#define musb_print_intrrx(w)
+#define musb_print_devctl(b)
+#define musb_print_config(b)
+#define musb_print_rxmaxp(w)
+#define musb_print_rxcsr(w)
+#define musb_print_txmaxp(w)
+#define musb_print_txcsr(w)
+
+#endif /* MUSB_DEBUG */
diff --git a/drivers/usb/musb/musb_udc.c b/drivers/usb/musb/musb_udc.c
new file mode 100644
index 0000000..fc43cf4
--- /dev/null
+++ b/drivers/usb/musb/musb_udc.c
@@ -0,0 +1,963 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * This file is a rewrite of the usb device part of
+ * repository git.omapzoom.org/repo/u-boot.git, branch master,
+ * file cpu/omap3/fastboot.c
+ *
+ * This is the unique part of its copyright :
+ *
+ * -------------------------------------------------------------------------
+ *
+ * (C) Copyright 2008 - 2009
+ * Windriver, <www.windriver.com>
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * -------------------------------------------------------------------------
+ *
+ * The details of connecting the device to the uboot usb device subsystem
+ * came from the old omap3 repository www.sakoman.net/u-boot-omap3.git,
+ * branch omap3-dev-usb, file drivers/usb/usbdcore_musb.c
+ *
+ * This is the unique part of its copyright :
+ *
+ * -------------------------------------------------------------------------
+ *
+ * (C) Copyright 2008 Texas Instruments Incorporated.
+ *
+ * Based on
+ * u-boot OMAP1510 USB drivers (drivers/usbdcore_omap1510.c)
+ * twl4030 init based on linux (drivers/i2c/chips/twl4030_usb.c)
+ *
+ * Author: Diego Dompe (diego.dompe at ridgerun.com)
+ *         Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * -------------------------------------------------------------------------
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <usb/musb_udc.h>
+#include "../gadget/ep0.h"
+#include "musb_core.h"
+#if defined(CONFIG_USB_OMAP3)
+#include "omap3.h"
+#elif defined(CONFIG_USB_DAVINCI)
+#include "davinci.h"
+#endif
+
+/* Define MUSB_DEBUG for debugging */
+/* #define MUSB_DEBUG */
+#include "musb_debug.h"
+
+#define MAX_ENDPOINT 15
+
+#define GET_ENDPOINT(dev,ep)						\
+(((struct usb_device_instance *)(dev))->bus->endpoint_array + ep)
+
+#define SET_EP0_STATE(s)						\
+do {									\
+	if ((0 <= (s)) && (SET_ADDRESS >= (s))) {			\
+		if ((s) != ep0_state) {					\
+			if ((debug_setup) && (debug_level > 1))		\
+				serial_printf("INFO : Changing state "  \
+					      "from %s to %s in %s at " \
+					      "line %d\n",		\
+					      ep0_state_strings[ep0_state],\
+					      ep0_state_strings[s],	\
+					      __PRETTY_FUNCTION__,	\
+					      __LINE__);		\
+			ep0_state = s;					\
+		}							\
+	} else {							\
+		if (debug_level > 0)					\
+			serial_printf("Error at %s %d with setting "	\
+				      "state %d is invalid\n",		\
+				      __PRETTY_FUNCTION__, __LINE__, s); \
+	}								\
+} while (0)
+
+/* static implies these initialized to 0 or NULL */
+static int debug_setup;
+static int debug_level;
+static struct musb_epinfo epinfo[MAX_ENDPOINT * 2];
+static enum ep0_state_enum {
+	IDLE = 0,
+	TX,
+	RX,
+	SET_ADDRESS
+} ep0_state = IDLE;
+static char *ep0_state_strings[4] = {
+	"IDLE",
+	"TX",
+	"RX",
+	"SET_ADDRESS",
+};
+
+static struct urb *ep0_urb;
+struct usb_endpoint_instance *ep0_endpoint;
+static struct usb_device_instance *udc_device;
+static int enabled;
+
+#ifdef MUSB_DEBUG
+static void musb_db_regs(void)
+{
+	u8 b;
+	u16 w;
+
+	b = readb(&musbr->faddr);
+	serial_printf("\tfaddr   0x%2.2x\n", b);
+
+	b = readb(&musbr->power);
+	musb_print_pwr(b);
+
+	w = readw(&musbr->ep[0].ep0.csr0);
+	musb_print_csr0(w);
+
+	b = readb(&musbr->devctl);
+	musb_print_devctl(b);
+
+	b = readb(&musbr->ep[0].ep0.configdata);
+	musb_print_config(b);
+
+	w = readw(&musbr->frame);
+	serial_printf("\tframe   0x%4.4x\n", w);
+
+	b = readb(&musbr->index);
+	serial_printf("\tindex   0x%2.2x\n", b);
+
+	w = readw(&musbr->ep[1].epN.rxmaxp);
+	musb_print_rxmaxp(w);
+
+	w = readw(&musbr->ep[1].epN.rxcsr);
+	musb_print_rxcsr(w);
+
+	w = readw(&musbr->ep[1].epN.txmaxp);
+	musb_print_txmaxp(w);
+
+	w = readw(&musbr->ep[1].epN.txcsr);
+	musb_print_txcsr(w);
+}
+#else
+#define musb_db_regs()
+#endif /* DEBUG_MUSB */
+
+static void musb_peri_softconnect(void)
+{
+	u8 power, devctl;
+	u8 intrusb;
+	u16 intrrx, intrtx;
+
+	/* Power off MUSB */
+	power = readb(&musbr->power);
+	power &= ~MUSB_POWER_SOFTCONN;
+	writeb(power, &musbr->power);
+
+	/* Read intr to clear */
+	intrusb = readb(&musbr->intrusb);
+	intrrx = readw(&musbr->intrrx);
+	intrtx = readw(&musbr->intrtx);
+
+	udelay(1000 * 1000); /* 1 sec */
+
+	/* Power on MUSB */
+	power = readb(&musbr->power);
+	power |= MUSB_POWER_SOFTCONN;
+	/*
+	 * The usb device interface is usb 1.1
+	 * Disable 2.0 high speed by clearring the hsenable bit.
+	 */
+	power &= ~MUSB_POWER_HSENAB;
+	writeb(power, &musbr->power);
+
+	/* Check if device is in b-peripheral mode */
+	devctl = readb(&musbr->devctl);
+	if (!(devctl & MUSB_DEVCTL_BDEVICE) ||
+	    (devctl & MUSB_DEVCTL_HM)) {
+		serial_printf("ERROR : Unsupport USB mode\n");
+		serial_printf("Check that mini-B USB cable is attached "
+			      "to the device\n");
+	}
+
+	if (debug_setup && (debug_level > 1))
+		musb_db_regs();
+}
+
+static void musb_peri_reset(void)
+{
+	if ((debug_setup) && (debug_level > 1))
+		serial_printf("INFO : %s reset\n", __PRETTY_FUNCTION__);
+
+	if (ep0_endpoint)
+		ep0_endpoint->endpoint_address = 0xff;
+
+	/* Sync sw and hw addresses */
+	writeb(udc_device->address, &musbr->faddr);
+
+	SET_EP0_STATE(IDLE);
+}
+
+static void musb_peri_resume(void)
+{
+	/* noop */
+}
+
+static void musb_peri_ep0_stall(void)
+{
+	u16 csr0;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+	csr0 |= MUSB_CSR0_P_SENDSTALL;
+	writew(csr0, &musbr->ep[0].ep0.csr0);
+	if ((debug_setup) && (debug_level > 1))
+		serial_printf("INFO : %s stall\n", __PRETTY_FUNCTION__);
+}
+
+static void musb_peri_ep0_ack_req(void)
+{
+	u16 csr0;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+	csr0 |= MUSB_CSR0_P_SVDRXPKTRDY;
+	writew(csr0, &musbr->ep[0].ep0.csr0);
+}
+
+static void musb_ep0_tx_ready(void)
+{
+	u16 csr0;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+	csr0 |= MUSB_CSR0_TXPKTRDY;
+	writew(csr0, &musbr->ep[0].ep0.csr0);
+}
+
+static void musb_ep0_tx_ready_and_last(void)
+{
+	u16 csr0;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+	csr0 |= (MUSB_CSR0_TXPKTRDY | MUSB_CSR0_P_DATAEND);
+	writew(csr0, &musbr->ep[0].ep0.csr0);
+}
+
+static void musb_peri_ep0_last(void)
+{
+	u16 csr0;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+	csr0 |= MUSB_CSR0_P_DATAEND;
+	writew(csr0, &musbr->ep[0].ep0.csr0);
+}
+
+static void musb_peri_ep0_set_address(void)
+{
+	u8 faddr;
+	writeb(udc_device->address, &musbr->faddr);
+
+	/* Verify */
+	faddr = readb(&musbr->faddr);
+	if (udc_device->address == faddr) {
+		SET_EP0_STATE(IDLE);
+		usbd_device_event_irq(udc_device, DEVICE_ADDRESS_ASSIGNED, 0);
+		if ((debug_setup) && (debug_level > 1))
+			serial_printf("INFO : %s Address set to %d\n",
+				      __PRETTY_FUNCTION__, udc_device->address);
+	} else {
+		if (debug_level > 0)
+			serial_printf("ERROR : %s Address missmatch "
+				      "sw %d vs hw %d\n",
+				      __PRETTY_FUNCTION__,
+				      udc_device->address, faddr);
+	}
+}
+
+static void musb_peri_rx_ack(unsigned int ep)
+{
+	u16 peri_rxcsr;
+
+	peri_rxcsr = readw(&musbr->ep[ep].epN.rxcsr);
+	peri_rxcsr &= ~MUSB_RXCSR_RXPKTRDY;
+	writew(peri_rxcsr, &musbr->ep[ep].epN.rxcsr);
+}
+
+static void musb_peri_tx_ready(unsigned int ep)
+{
+	u16 peri_txcsr;
+
+	peri_txcsr = readw(&musbr->ep[ep].epN.txcsr);
+	peri_txcsr |= MUSB_TXCSR_TXPKTRDY;
+	writew(peri_txcsr, &musbr->ep[ep].epN.txcsr);
+}
+
+static void musb_peri_ep0_zero_data_request(int err)
+{
+	musb_peri_ep0_ack_req();
+
+	if (err) {
+		musb_peri_ep0_stall();
+		SET_EP0_STATE(IDLE);
+	} else {
+
+		musb_peri_ep0_last();
+
+		/* USBD state */
+		switch (ep0_urb->device_request.bRequest) {
+		case USB_REQ_SET_ADDRESS:
+			if ((debug_setup) && (debug_level > 1))
+				serial_printf("INFO : %s received set "
+					      "address\n", __PRETTY_FUNCTION__);
+			break;
+
+		case USB_REQ_SET_CONFIGURATION:
+			if ((debug_setup) && (debug_level > 1))
+				serial_printf("INFO : %s Configured\n",
+					      __PRETTY_FUNCTION__);
+			usbd_device_event_irq(udc_device, DEVICE_CONFIGURED, 0);
+			break;
+		}
+
+		/* EP0 state */
+		if (USB_REQ_SET_ADDRESS == ep0_urb->device_request.bRequest) {
+			SET_EP0_STATE(SET_ADDRESS);
+		} else {
+			SET_EP0_STATE(IDLE);
+		}
+	}
+}
+
+static void musb_peri_ep0_rx_data_request(void)
+{
+	/*
+	 * This is the completion of the data OUT / RX
+	 *
+	 * Host is sending data to ep0 that is not
+	 * part of setup.  This comes from the cdc_recv_setup
+	 * op that is device specific.
+	 *
+	 */
+	musb_peri_ep0_ack_req();
+
+	ep0_endpoint->rcv_urb = ep0_urb;
+	ep0_urb->actual_length = 0;
+	SET_EP0_STATE(RX);
+}
+
+static void musb_peri_ep0_tx_data_request(int err)
+{
+	if (err) {
+		musb_peri_ep0_stall();
+		SET_EP0_STATE(IDLE);
+	} else {
+		musb_peri_ep0_ack_req();
+
+		ep0_endpoint->tx_urb = ep0_urb;
+		ep0_endpoint->sent = 0;
+		SET_EP0_STATE(TX);
+	}
+}
+
+static void musb_peri_ep0_idle(void)
+{
+	u16 count0;
+	int err;
+	u16 csr0;
+
+	/*
+	 * Verify addresses
+	 * A lot of confusion can be caused if the address
+	 * in software, udc layer, does not agree with the
+	 * hardware.  Since the setting of the hardware address
+	 * must be set after the set address request, the
+	 * usb state machine is out of sync for a few frame.
+	 * It is a good idea to run this check when changes
+	 * are made to the state machine.
+	 */
+	if ((debug_level > 0) &&
+	    (ep0_state != SET_ADDRESS)) {
+		u8 faddr;
+
+		faddr = readb(&musbr->faddr);
+		if (udc_device->address != faddr) {
+			serial_printf("ERROR : %s addresses do not"
+				      "match sw %d vs hw %d\n",
+				      __PRETTY_FUNCTION__,
+				      udc_device->address, faddr);
+			udelay(1000 * 1000);
+			hang();
+		}
+	}
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+
+	if (!(MUSB_CSR0_RXPKTRDY & csr0))
+		goto end;
+
+	count0 = readw(&musbr->ep[0].ep0.count0);
+	if (count0 == 0)
+		goto end;
+
+	if (count0 != 8) {
+		if ((debug_setup) && (debug_level > 1))
+			serial_printf("WARN : %s SETUP incorrect size %d\n",
+				      __PRETTY_FUNCTION__, count0);
+		musb_peri_ep0_stall();
+		goto end;
+	}
+
+	read_fifo(0, count0, &ep0_urb->device_request);
+
+	if (debug_level > 2)
+		print_usb_device_request(&ep0_urb->device_request);
+
+	if (ep0_urb->device_request.wLength == 0) {
+		err = ep0_recv_setup(ep0_urb);
+
+		/* Zero data request */
+		musb_peri_ep0_zero_data_request(err);
+	} else {
+		/* Is data coming or going ? */
+		u8 reqType = ep0_urb->device_request.bmRequestType;
+
+		if (USB_REQ_DEVICE2HOST == (reqType & USB_REQ_DIRECTION_MASK)) {
+			err = ep0_recv_setup(ep0_urb);
+			/* Device to host */
+			musb_peri_ep0_tx_data_request(err);
+		} else {
+			/*
+			 * Host to device
+			 *
+			 * The RX routine will call ep0_recv_setup
+			 * when the data packet has arrived.
+			 */
+			musb_peri_ep0_rx_data_request();
+		}
+	}
+
+end:
+	return;
+}
+
+static void musb_peri_ep0_rx(void)
+{
+	/*
+	 * This is the completion of the data OUT / RX
+	 *
+	 * Host is sending data to ep0 that is not
+	 * part of setup.  This comes from the cdc_recv_setup
+	 * op that is device specific.
+	 *
+	 * Pass the data back to driver ep0_recv_setup which
+	 * should give the cdc_recv_setup the chance to handle
+	 * the rx
+	 */
+	u16 csr0;
+	u16 count0;
+
+	if (debug_level > 3) {
+		if (0 != ep0_urb->actual_length) {
+			serial_printf("%s finished ? %d of %d\n",
+				      __PRETTY_FUNCTION__,
+				      ep0_urb->actual_length,
+				      ep0_urb->device_request.wLength);
+		}
+	}
+
+	if (ep0_urb->device_request.wLength == ep0_urb->actual_length) {
+		musb_peri_ep0_last();
+		SET_EP0_STATE(IDLE);
+		ep0_recv_setup(ep0_urb);
+		return;
+	}
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+	if (!(MUSB_CSR0_RXPKTRDY & csr0))
+		return;
+
+	count0 = readw(&musbr->ep[0].ep0.count0);
+
+	if (count0) {
+		struct usb_endpoint_instance *endpoint;
+		u32 length;
+		u8 *data;
+
+		endpoint = ep0_endpoint;
+		if (endpoint && endpoint->rcv_urb) {
+			struct urb *urb = endpoint->rcv_urb;
+			unsigned int remaining_space = urb->buffer_length -
+				urb->actual_length;
+
+			if (remaining_space) {
+				int urb_bad = 0; /* urb is good */
+
+				if (count0 > remaining_space)
+					length = remaining_space;
+				else
+					length = count0;
+
+				data = (u8 *) urb->buffer_data;
+				data += urb->actual_length;
+
+				/* The common musb fifo reader */
+				read_fifo(0, length, data);
+
+				musb_peri_ep0_ack_req();
+
+				/*
+				 * urb's actual_length is updated in
+				 * usbd_rcv_complete
+				 */
+				usbd_rcv_complete(endpoint, length, urb_bad);
+
+			} else {
+				if (debug_level > 0)
+					serial_printf("ERROR : %s no space in "
+						      "rcv buffer\n",
+						      __PRETTY_FUNCTION__);
+			}
+		} else {
+			if (debug_level > 0)
+				serial_printf("ERROR : %s problem with "
+					      "endpoint\n",
+					      __PRETTY_FUNCTION__);
+		}
+	} else {
+		if (debug_level > 0)
+			serial_printf("ERROR : %s with nothing to do\n",
+				      __PRETTY_FUNCTION__);
+	}
+}
+
+static void musb_peri_ep0_tx(void)
+{
+	u16 csr0;
+	int transfer_size = 0;
+	unsigned int p, pm;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+
+	/* Check for pending tx */
+	if (csr0 & MUSB_CSR0_TXPKTRDY)
+		goto end;
+
+	/* Check if this is the last packet sent */
+	if (ep0_endpoint->sent >= ep0_urb->actual_length) {
+		SET_EP0_STATE(IDLE);
+		goto end;
+	}
+
+	transfer_size = ep0_urb->actual_length - ep0_endpoint->sent;
+	/* Is the transfer size negative ? */
+	if (transfer_size <= 0) {
+		if (debug_level > 0)
+			serial_printf("ERROR : %s problem with the"
+				      " transfer size %d\n",
+				      __PRETTY_FUNCTION__,
+				      transfer_size);
+		SET_EP0_STATE(IDLE);
+		goto end;
+	}
+
+	/* Truncate large transfers to the fifo size */
+	if (transfer_size > ep0_endpoint->tx_packetSize)
+		transfer_size = ep0_endpoint->tx_packetSize;
+
+	write_fifo(0, transfer_size, &ep0_urb->buffer[ep0_endpoint->sent]);
+	ep0_endpoint->sent += transfer_size;
+
+	/* Done or more to send ? */
+	if (ep0_endpoint->sent >= ep0_urb->actual_length)
+		musb_ep0_tx_ready_and_last();
+	else
+		musb_ep0_tx_ready();
+
+	/* Wait a bit */
+	pm = 10;
+	for (p = 0; p < pm; p++) {
+		csr0 = readw(&musbr->ep[0].ep0.csr0);
+		if (!(csr0 & MUSB_CSR0_TXPKTRDY))
+			break;
+
+		/* Double the delay. */
+		udelay(1 << pm);
+	}
+
+	if ((ep0_endpoint->sent >= ep0_urb->actual_length) && (p < pm))
+		SET_EP0_STATE(IDLE);
+
+end:
+	return;
+}
+
+static void musb_peri_ep0(void)
+{
+	u16 csr0;
+
+	if (SET_ADDRESS == ep0_state)
+		return;
+
+	csr0 = readw(&musbr->ep[0].ep0.csr0);
+
+	/* Error conditions */
+	if (MUSB_CSR0_P_SENTSTALL & csr0) {
+		csr0 &= ~MUSB_CSR0_P_SENTSTALL;
+		writew(csr0, &musbr->ep[0].ep0.csr0);
+		SET_EP0_STATE(IDLE);
+	}
+	if (MUSB_CSR0_P_SETUPEND & csr0) {
+		csr0 |= MUSB_CSR0_P_SVDSETUPEND;
+		writew(csr0, &musbr->ep[0].ep0.csr0);
+		SET_EP0_STATE(IDLE);
+		if ((debug_setup) && (debug_level > 1))
+			serial_printf("WARN: %s SETUPEND\n",
+				      __PRETTY_FUNCTION__);
+	}
+
+	/* Normal states */
+	if (IDLE == ep0_state)
+		musb_peri_ep0_idle();
+
+	if (TX == ep0_state)
+		musb_peri_ep0_tx();
+
+	if (RX == ep0_state)
+		musb_peri_ep0_rx();
+}
+
+static void musb_peri_rx_ep(unsigned int ep)
+{
+	u16 peri_rxcount = readw(&musbr->ep[ep].epN.rxcount);
+
+	if (peri_rxcount) {
+		struct usb_endpoint_instance *endpoint;
+		u32 length;
+		u8 *data;
+
+		endpoint = GET_ENDPOINT(udc_device, ep);
+		if (endpoint && endpoint->rcv_urb) {
+			struct urb *urb = endpoint->rcv_urb;
+			unsigned int remaining_space = urb->buffer_length -
+				urb->actual_length;
+
+			if (remaining_space) {
+				int urb_bad = 0; /* urb is good */
+
+				if (peri_rxcount > remaining_space)
+					length = remaining_space;
+				else
+					length = peri_rxcount;
+
+				data = (u8 *) urb->buffer_data;
+				data += urb->actual_length;
+
+				/* The common musb fifo reader */
+				read_fifo(ep, length, data);
+
+				musb_peri_rx_ack(ep);
+
+				/*
+				 * urb's actual_length is updated in
+				 * usbd_rcv_complete
+				 */
+				usbd_rcv_complete(endpoint, length, urb_bad);
+
+			} else {
+				if (debug_level > 0)
+					serial_printf("ERROR : %s %d no space "
+						      "in rcv buffer\n",
+						      __PRETTY_FUNCTION__, ep);
+			}
+		} else {
+			if (debug_level > 0)
+				serial_printf("ERROR : %s %d problem with "
+					      "endpoint\n",
+					      __PRETTY_FUNCTION__, ep);
+		}
+
+	} else {
+		if (debug_level > 0)
+			serial_printf("ERROR : %s %d with nothing to do\n",
+				      __PRETTY_FUNCTION__, ep);
+	}
+}
+
+static void musb_peri_rx(u16 intr)
+{
+	unsigned int ep;
+
+	/* Check for EP0 */
+	if (0x01 & intr)
+		musb_peri_ep0();
+
+	for (ep = 1; ep < 16; ep++) {
+		if ((1 << ep) & intr)
+			musb_peri_rx_ep(ep);
+	}
+}
+
+static void musb_peri_tx(u16 intr)
+{
+	/* Check for EP0 */
+	if (0x01 & intr)
+		musb_peri_ep0_tx();
+
+	/*
+	 * Use this in the future when handling epN tx
+	 *
+	 * u8 ep;
+	 *
+	 * for (ep = 1; ep < 16; ep++) {
+	 *	if ((1 << ep) & intr) {
+	 *		/ * handle tx for this endpoint * /
+	 *	}
+	 * }
+	 */
+}
+
+void udc_irq(void)
+{
+	/* This is a high freq called function */
+	if (enabled) {
+		u8 intrusb;
+
+		intrusb = readb(&musbr->intrusb);
+
+		/*
+		 * See drivers/usb/gadget/mpc8xx_udc.c for
+		 * state diagram going from detached through
+		 * configuration.
+		 */
+		if (MUSB_INTR_RESUME & intrusb) {
+			usbd_device_event_irq(udc_device,
+					      DEVICE_BUS_ACTIVITY, 0);
+			musb_peri_resume();
+		}
+
+		musb_peri_ep0();
+
+		if (MUSB_INTR_RESET & intrusb) {
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+			musb_peri_reset();
+		}
+
+		if (MUSB_INTR_DISCONNECT & intrusb) {
+			/* cable unplugged from hub/host */
+			usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+			musb_peri_reset();
+			usbd_device_event_irq(udc_device, DEVICE_HUB_RESET, 0);
+		}
+
+		if (MUSB_INTR_SOF & intrusb) {
+			usbd_device_event_irq(udc_device,
+					      DEVICE_BUS_ACTIVITY, 0);
+			musb_peri_resume();
+		}
+
+		if (MUSB_INTR_SUSPEND & intrusb) {
+			usbd_device_event_irq(udc_device,
+					      DEVICE_BUS_INACTIVE, 0);
+		}
+
+		if (ep0_state != SET_ADDRESS) {
+			u16 intrrx, intrtx;
+
+			intrrx = readw(&musbr->intrrx);
+			intrtx = readw(&musbr->intrtx);
+
+			if (intrrx)
+				musb_peri_rx(intrrx);
+
+			if (intrtx)
+				musb_peri_tx(intrtx);
+		} else {
+			if (MUSB_INTR_SOF & intrusb) {
+				u8 faddr;
+				faddr = readb(&musbr->faddr);
+				/*
+				 * Setting of the address can fail.
+				 * Normally it succeeds the second time.
+				 */
+				if (udc_device->address != faddr)
+					musb_peri_ep0_set_address();
+			}
+		}
+	}
+}
+
+void udc_set_nak(int ep_num)
+{
+	/* noop */
+}
+
+void udc_unset_nak(int ep_num)
+{
+	/* noop */
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+	int ret = 0;
+
+	/* Transmit only if the hardware is available */
+	if (endpoint->tx_urb && endpoint->state == 0) {
+		unsigned int ep = endpoint->endpoint_address &
+			USB_ENDPOINT_NUMBER_MASK;
+
+		u16 peri_txcsr = readw(&musbr->ep[ep].epN.txcsr);
+
+		/* Error conditions */
+		if (peri_txcsr & MUSB_TXCSR_P_UNDERRUN) {
+			peri_txcsr &= ~MUSB_TXCSR_P_UNDERRUN;
+			writew(peri_txcsr, &musbr->ep[ep].epN.txcsr);
+		}
+
+		if (debug_level > 1)
+			musb_print_txcsr(peri_txcsr);
+
+		/* Check if a packet is waiting to be sent */
+		if (!(peri_txcsr & MUSB_TXCSR_TXPKTRDY)) {
+			u32 length;
+			u8 *data;
+			struct urb *urb = endpoint->tx_urb;
+			unsigned int remaining_packet = urb->actual_length -
+				endpoint->sent;
+
+			if (endpoint->tx_packetSize < remaining_packet)
+				length = endpoint->tx_packetSize;
+			else
+				length = remaining_packet;
+
+			data = (u8 *) urb->buffer;
+			data += endpoint->sent;
+
+			/* common musb fifo function */
+			write_fifo(ep, length, data);
+
+			musb_peri_tx_ready(ep);
+
+			endpoint->last = length;
+			/* usbd_tx_complete will take care of updating 'sent' */
+			usbd_tx_complete(endpoint);
+		}
+	} else {
+		if (debug_level > 0)
+			serial_printf("ERROR : %s Problem with urb %p "
+				      "or ep state %d\n",
+				      __PRETTY_FUNCTION__,
+				      endpoint->tx_urb, endpoint->state);
+	}
+
+	return ret;
+}
+
+void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
+		  struct usb_endpoint_instance *endpoint)
+{
+	if (0 == id) {
+		/* EP0 */
+		ep0_endpoint = endpoint;
+		ep0_endpoint->endpoint_address = 0xff;
+		ep0_urb = usbd_alloc_urb(device, endpoint);
+	} else if (MAX_ENDPOINT >= id) {
+		int ep_addr;
+
+		/* Check the direction */
+		ep_addr = endpoint->endpoint_address;
+		if (USB_DIR_IN == (ep_addr & USB_ENDPOINT_DIR_MASK)) {
+			/* IN */
+			epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize;
+		} else {
+			/* OUT */
+			epinfo[id * 2].epsize = endpoint->rcv_packetSize;
+		}
+
+		musb_configure_ep(&epinfo[0],
+				  sizeof(epinfo) / sizeof(struct musb_epinfo));
+	} else {
+		if (debug_level > 0)
+			serial_printf("ERROR : %s endpoint request %d "
+				      "exceeds maximum %d\n",
+				      __PRETTY_FUNCTION__, id, MAX_ENDPOINT);
+	}
+}
+
+void udc_connect(void)
+{
+	/* noop */
+}
+
+void udc_disconnect(void)
+{
+	/* noop */
+}
+
+void udc_enable(struct usb_device_instance *device)
+{
+	/* Save the device structure pointer */
+	udc_device = device;
+
+	enabled = 1;
+}
+
+void udc_disable(void)
+{
+	enabled = 0;
+}
+
+void udc_startup_events(struct usb_device_instance *device)
+{
+	/* The DEVICE_INIT event puts the USB device in the state STATE_INIT. */
+	usbd_device_event_irq(device, DEVICE_INIT, 0);
+
+	/*
+	 * The DEVICE_CREATE event puts the USB device in the state
+	 * STATE_ATTACHED.
+	 */
+	usbd_device_event_irq(device, DEVICE_CREATE, 0);
+
+	/* Resets the address to 0 */
+	usbd_device_event_irq(device, DEVICE_RESET, 0);
+
+	udc_enable(device);
+}
+
+int udc_init(void)
+{
+	int ret;
+	int ep_loop;
+
+	ret = musb_platform_init();
+	if (ret < 0)
+		goto end;
+
+	/* Configure all the endpoint FIFO's and start usb controller */
+	musbr = musb_cfg.regs;
+
+	/* Initialize the endpoints */
+	for (ep_loop = 0; ep_loop < MAX_ENDPOINT * 2; ep_loop++) {
+		epinfo[ep_loop].epnum = (ep_loop / 2) + 1;
+		epinfo[ep_loop].epdir = ep_loop % 2; /* OUT, IN */
+		epinfo[ep_loop].epsize = 0;
+	}
+
+	musb_peri_softconnect();
+
+	ret = 0;
+end:
+
+	return ret;
+}
diff --git a/drivers/usb/musb/omap3.c b/drivers/usb/musb/omap3.c
new file mode 100644
index 0000000..3e502e7
--- /dev/null
+++ b/drivers/usb/musb/omap3.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * This is file is based on
+ * repository git.gitorious.org/u-boot-omap3/mainline.git,
+ * branch omap3-dev-usb, file drivers/usb/host/omap3530_usb.c
+ *
+ * This is the unique part of its copyright :
+ *
+ * ------------------------------------------------------------------------
+ *
+ * Copyright (c) 2009 Texas Instruments
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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
+ */
+
+#include <twl4030.h>
+#include "omap3.h"
+
+static int platform_needs_initialization = 1;
+
+struct musb_config musb_cfg = {
+	(struct	musb_regs *)MENTOR_USB0_BASE,
+	OMAP3_USB_TIMEOUT,
+	0
+};
+
+/*
+ * OMAP3 USB OTG registers.
+ */
+struct omap3_otg_regs {
+	u32	revision;
+	u32	sysconfig;
+	u32	sysstatus;
+	u32	interfsel;
+	u32	simenable;
+	u32	forcestdby;
+};
+
+static struct omap3_otg_regs *otg;
+
+#define OMAP3_OTG_SYSCONFIG_SMART_STANDBY_MODE		0x2000
+#define OMAP3_OTG_SYSCONFIG_NO_STANDBY_MODE		0x1000
+#define OMAP3_OTG_SYSCONFIG_SMART_IDLE_MODE		0x0010
+#define OMAP3_OTG_SYSCONFIG_NO_IDLE_MODE		0x0008
+#define OMAP3_OTG_SYSCONFIG_ENABLEWAKEUP		0x0004
+#define OMAP3_OTG_SYSCONFIG_SOFTRESET			0x0002
+#define OMAP3_OTG_SYSCONFIG_AUTOIDLE			0x0001
+
+#define OMAP3_OTG_SYSSTATUS_RESETDONE			0x0001
+
+#define OMAP3_OTG_INTERFSEL_OMAP			0x0001
+
+#define OMAP3_OTG_FORCESTDBY_STANDBY			0x0001
+
+
+#ifdef DEBUG_MUSB_OMAP3
+static void musb_db_otg_regs(void)
+{
+	u32 l;
+	l = readl(&otg->revision);
+	serial_printf("OTG_REVISION 0x%x\n", l);
+	l = readl(&otg->sysconfig);
+	serial_printf("OTG_SYSCONFIG 0x%x\n", l);
+	l = readl(&otg->sysstatus);
+	serial_printf("OTG_SYSSTATUS 0x%x\n", l);
+	l = readl(&otg->interfsel);
+	serial_printf("OTG_INTERFSEL 0x%x\n", l);
+	l = readl(&otg->forcestdby);
+	serial_printf("OTG_FORCESTDBY 0x%x\n", l);
+}
+#endif
+
+int musb_platform_init(void)
+{
+	int ret = -1;
+
+	if (platform_needs_initialization) {
+		u32 stdby;
+
+		if (twl4030_usb_ulpi_init()) {
+			serial_printf("ERROR: %s Could not initialize PHY\n",
+				__PRETTY_FUNCTION__);
+			goto end;
+		}
+
+		otg = (struct omap3_otg_regs *)OMAP3_OTG_BASE;
+
+		/* Set OTG to always be on */
+		writel(OMAP3_OTG_SYSCONFIG_NO_STANDBY_MODE |
+		       OMAP3_OTG_SYSCONFIG_NO_IDLE_MODE, &otg->sysconfig);
+
+		/* Set the interface */
+		writel(OMAP3_OTG_INTERFSEL_OMAP, &otg->interfsel);
+
+		/* Clear force standby */
+		stdby = readl(&otg->forcestdby);
+		stdby &= ~OMAP3_OTG_FORCESTDBY_STANDBY;
+		writel(stdby, &otg->forcestdby);
+
+		platform_needs_initialization = 0;
+	}
+
+	ret = platform_needs_initialization;
+end:
+	return ret;
+
+}
+
+void musb_platform_deinit(void)
+{
+	/* noop */
+}
diff --git a/drivers/usb/musb/omap3.h b/drivers/usb/musb/omap3.h
new file mode 100644
index 0000000..20fc9d2
--- /dev/null
+++ b/drivers/usb/musb/omap3.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * This file is based on the file drivers/usb/musb/davinci.h
+ *
+ * This is the unique part of its copyright:
+ *
+ * --------------------------------------------------------------------
+ *
+ * Copyright (c) 2008 Texas Instruments
+ * Author: Thomas Abraham t-abraham at ti.com, Texas Instruments
+ *
+ * --------------------------------------------------------------------
+ *
+ * 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 _MUSB_OMAP3_H_
+#define _MUSB_OMAP3_H_
+
+#include "musb_core.h"
+
+/* Base address of MUSB registers */
+#define MENTOR_USB0_BASE (OMAP34XX_CORE_L4_IO_BASE + 0xAB000)
+
+/* Base address of OTG registers */
+#define OMAP3_OTG_BASE (MENTOR_USB0_BASE + 0x400)
+
+/* Timeout for USB module */
+#define OMAP3_USB_TIMEOUT 0x3FFFFFF
+
+int musb_platform_init(void);
+
+#endif /* _MUSB_OMAP3_H */
+
diff --git a/include/usb.h b/include/usb.h
index 378a23b..198d5bb 100644
--- a/include/usb.h
+++ b/include/usb.h
@@ -131,7 +131,8 @@ struct usb_device {
 #if defined(CONFIG_USB_UHCI) || defined(CONFIG_USB_OHCI) || \
 	defined(CONFIG_USB_EHCI) || defined(CONFIG_USB_OHCI_NEW) || \
 	defined(CONFIG_USB_SL811HS) || defined(CONFIG_USB_ISP116X_HCD) || \
-	defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI)
+	defined(CONFIG_USB_R8A66597_HCD) || defined(CONFIG_USB_DAVINCI) || \
+	defined(CONFIG_USB_OMAP3)
 
 int usb_lowlevel_init(void);
 int usb_lowlevel_stop(void);
diff --git a/include/usb/musb_udc.h b/include/usb/musb_udc.h
new file mode 100644
index 0000000..ef37dbb
--- /dev/null
+++ b/include/usb/musb_udc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * 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 __MUSB_UDC_H__
+#define __MUSB_UDC_H__
+
+#include <usbdevice.h>
+
+/* UDC level routines */
+void udc_irq(void);
+void udc_set_nak(int ep_num);
+void udc_unset_nak(int ep_num);
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
+		  struct usb_endpoint_instance *endpoint);
+void udc_connect(void);
+void udc_disconnect(void);
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+void udc_startup_events(struct usb_device_instance *device);
+int udc_init(void);
+
+/* usbtty */
+#ifdef CONFIG_USB_TTY
+
+#define EP0_MAX_PACKET_SIZE	64 /* MUSB_EP0_FIFOSIZE */
+#define UDC_INT_ENDPOINT	1
+#define UDC_INT_PACKET_SIZE	64
+#define UDC_OUT_ENDPOINT	2
+#define UDC_OUT_PACKET_SIZE	64
+#define UDC_IN_ENDPOINT		3
+#define UDC_IN_PACKET_SIZE	64
+#define UDC_BULK_PACKET_SIZE	64
+
+#endif /* CONFIG_USB_TTY */
+
+#endif /* __MUSB_UDC_H__ */
+
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 5/8] OMAP3 zoom1 Add usbtty configuration
  2009-09-28 16:34       ` [U-Boot] [PATCH 4/8] OMAP3 Add usb device support y at windriver.com
@ 2009-09-28 16:35         ` y at windriver.com
  2009-09-28 16:35           ` [U-Boot] [PATCH 6/8] OMAP3 beagle " y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:35 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

The primary console of zoom1 is the serial out from the jumpers
accessed by removing the back panel.

A secondary console is to use the usbtty.  The user can set this
manually by doing

setenv stdout usbtty; setenv stdin usbtty; setenv stderr usbtty
saveenv

usbtty will be usable by accessing the /dev/ttyACM0 on a linux host.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 include/configs/omap3_zoom1.h |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/include/configs/omap3_zoom1.h b/include/configs/omap3_zoom1.h
index b55b8f0..c4527e6 100644
--- a/include/configs/omap3_zoom1.h
+++ b/include/configs/omap3_zoom1.h
@@ -99,6 +99,21 @@
 #define CONFIG_OMAP3_MMC		1
 #define CONFIG_DOS_PARTITION		1
 
+/* USB */
+#define CONFIG_MUSB_UDC			1
+#define CONFIG_USB_OMAP3		1
+#define CONFIG_TWL4030_USB		1
+
+/* USB device configuration */
+#define CONFIG_USB_DEVICE		1
+#define CONFIG_USB_TTY			1
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV	1
+/* Change these to suit your needs */
+#define CONFIG_USBD_VENDORID		0x0451
+#define CONFIG_USBD_PRODUCTID		0x5678
+#define CONFIG_USBD_MANUFACTURER	"Texas Instruments"
+#define CONFIG_USBD_PRODUCT_NAME	"Zoom1"
+
 /* commands to include */
 #include <config_cmd_default.h>
 
@@ -161,6 +176,7 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"loadaddr=0x82000000\0" \
+	"usbtty=cdc_acm\0" \
 	"console=ttyS2,115200n8\0" \
 	"videomode=1024x768 at 60,vxres=1024,vyres=768\0" \
 	"videospec=omapfb:vram:2M,vram:4M\0" \
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 6/8] OMAP3 beagle Add usbtty configuration
  2009-09-28 16:35         ` [U-Boot] [PATCH 5/8] OMAP3 zoom1 Add usbtty configuration y at windriver.com
@ 2009-09-28 16:35           ` y at windriver.com
  2009-09-28 16:35             ` [U-Boot] [PATCH 7/8] USBTTY make some function declarations easier to use y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:35 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

The primary console of beagle is the serial header.

A secondary console is to use the usbtty.  The user can set this
manually by doing

setenv stdout usbtty; setenv stdin usbtty; setenv stderr usbtty
saveenv

usbtty will be usable by accessing the /dev/ttyACM0 on a linux host.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 include/configs/omap3_beagle.h |   16 ++++++++++++++++
 1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
index 55eeb94..253cdba 100644
--- a/include/configs/omap3_beagle.h
+++ b/include/configs/omap3_beagle.h
@@ -98,6 +98,21 @@
 #define CONFIG_OMAP3_MMC		1
 #define CONFIG_DOS_PARTITION		1
 
+/* USB */
+#define CONFIG_MUSB_UDC			1
+#define CONFIG_USB_OMAP3		1
+#define CONFIG_TWL4030_USB		1
+
+/* USB device configuration */
+#define CONFIG_USB_DEVICE		1
+#define CONFIG_USB_TTY			1
+#define CONFIG_SYS_CONSOLE_IS_IN_ENV	1
+/* Change these to suit your needs */
+#define CONFIG_USBD_VENDORID		0x0451
+#define CONFIG_USBD_PRODUCTID		0x5678
+#define CONFIG_USBD_MANUFACTURER	"Texas Instruments"
+#define CONFIG_USBD_PRODUCT_NAME	"Beagle"
+
 /* commands to include */
 #include <config_cmd_default.h>
 
@@ -164,6 +179,7 @@
 
 #define CONFIG_EXTRA_ENV_SETTINGS \
 	"loadaddr=0x82000000\0" \
+	"usbtty=cdc_acm\0" \
 	"console=ttyS2,115200n8\0" \
 	"videomode=1024x768 at 60,vxres=1024,vyres=768\0" \
 	"videospec=omapfb:vram:2M,vram:4M\0" \
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 7/8] USBTTY make some function declarations easier to use.
  2009-09-28 16:35           ` [U-Boot] [PATCH 6/8] OMAP3 beagle " y at windriver.com
@ 2009-09-28 16:35             ` y at windriver.com
  2009-09-28 16:35               ` [U-Boot] [PATCH 8/8] OMAP3 zoom2 Use usbtty if the debug board is not connected y at windriver.com
  0 siblings, 1 reply; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:35 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

Zoom2 needs to use these declarations and the include directory is a
better place from them than in the middle of the driver directory.
It did not make sense to create a new file for just a couple of
lines so they were appended to the serial.h

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 include/serial.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/serial.h b/include/serial.h
index 821b583..2c150ff 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -59,4 +59,10 @@ extern void serial_stdio_init(void);
 extern int serial_assign(char * name);
 extern void serial_reinit_all(void);
 
+/* For usbtty */
+extern int usbtty_getc(void);
+extern void usbtty_putc(const char c);
+extern void usbtty_puts(const char *str);
+extern int usbtty_tstc(void);
+
 #endif
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 8/8] OMAP3 zoom2 Use usbtty if the debug board is not connected.
  2009-09-28 16:35             ` [U-Boot] [PATCH 7/8] USBTTY make some function declarations easier to use y at windriver.com
@ 2009-09-28 16:35               ` y at windriver.com
  0 siblings, 0 replies; 14+ messages in thread
From: y at windriver.com @ 2009-09-28 16:35 UTC (permalink / raw)
  To: u-boot

From: Tom Rix <Tom.Rix@windriver.com>

The preferred serial output comes from the debug board.
When the debug board is disconnected, fall back on using
usbtty from the usb connector on the Zoom2 board.

This shows up as /dev/ttyACM0 in a linux host.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 board/logicpd/zoom2/zoom2_serial.c |   12 ++++++++----
 include/configs/omap3_zoom2.h      |   17 +++++++++++++++++
 include/serial.h                   |   12 ++++++++++++
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/board/logicpd/zoom2/zoom2_serial.c b/board/logicpd/zoom2/zoom2_serial.c
index a3d777d..ba58e39 100644
--- a/board/logicpd/zoom2/zoom2_serial.c
+++ b/board/logicpd/zoom2/zoom2_serial.c
@@ -86,6 +86,8 @@ void quad_putc_dev (unsigned long base, const char c)
 			quad_putc_dev (base, '\r');
 
 		NS16550_putc ((NS16550_t) base, c);
+	} else {
+		usbtty_putc(c);
 	}
 }
 
@@ -94,6 +96,8 @@ void quad_puts_dev (unsigned long base, const char *s)
 	if (zoom2_debug_board_connected ()) {
 		while ((s != NULL) && (*s != '\0'))
 			quad_putc_dev (base, *s++);
+	} else {
+		usbtty_puts(s);
 	}
 }
 
@@ -101,16 +105,16 @@ int quad_getc_dev (unsigned long base)
 {
 	if (zoom2_debug_board_connected ())
 		return NS16550_getc ((NS16550_t) base);
-	else
-		return 0;
+
+	return usbtty_getc();
 }
 
 int quad_tstc_dev (unsigned long base)
 {
 	if (zoom2_debug_board_connected ())
 		return NS16550_tstc ((NS16550_t) base);
-	else
-		return 0;
+
+	return usbtty_tstc();
 }
 
 void quad_setbrg_dev (unsigned long base)
diff --git a/include/configs/omap3_zoom2.h b/include/configs/omap3_zoom2.h
index 75ab980..8d24efe 100644
--- a/include/configs/omap3_zoom2.h
+++ b/include/configs/omap3_zoom2.h
@@ -123,6 +123,20 @@
 #define CONFIG_OMAP3_GPIO_3 /* board revision */
 #define CONFIG_OMAP3_GPIO_5 /* debug board detection, ZOOM2_LED_BLUE */
 
+/* USB */
+#define CONFIG_MUSB_UDC			1
+#define CONFIG_USB_OMAP3		1
+#define CONFIG_TWL4030_USB		1
+
+/* USB device configuration */
+#define CONFIG_USB_DEVICE		1
+#define CONFIG_USB_TTY			1
+/* Change these to suit your needs */
+#define CONFIG_USBD_VENDORID		0x0451
+#define CONFIG_USBD_PRODUCTID		0x5678
+#define CONFIG_USBD_MANUFACTURER	"Texas Instruments"
+#define CONFIG_USBD_PRODUCT_NAME	"Zoom2"
+
 /* commands to include */
 #include <config_cmd_default.h>
 
@@ -170,6 +184,9 @@
 /* Environment information */
 #define CONFIG_BOOTDELAY		10
 
+#define CONFIG_EXTRA_ENV_SETTINGS \
+	"usbtty=cdc_acm\0" \
+
 /*
  * Miscellaneous configurable options
  */
diff --git a/include/serial.h b/include/serial.h
index 2c150ff..c0e1bce 100644
--- a/include/serial.h
+++ b/include/serial.h
@@ -60,9 +60,21 @@ extern int serial_assign(char * name);
 extern void serial_reinit_all(void);
 
 /* For usbtty */
+#ifdef CONFIG_USB_TTY
+
 extern int usbtty_getc(void);
 extern void usbtty_putc(const char c);
 extern void usbtty_puts(const char *str);
 extern int usbtty_tstc(void);
 
+#else
+
+/* stubs */
+#define usbtty_getc() 0
+#define usbtty_putc(a)
+#define usbtty_puts(a)
+#define usbtty_tstc() 0
+
+#endif /* CONFIG_USB_TTY */
+
 #endif
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support
  2009-09-28 16:37   ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup Tom Rix
@ 2009-09-28 16:37     ` Tom Rix
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Rix @ 2009-09-28 16:37 UTC (permalink / raw)
  To: u-boot

The twl4030 provides a PHY device for connecting a link device,
like musb, to physical connection.

This change adds the twl4030 usb registers and functions for
initializing the PHY as required by omap3.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 Makefile                  |    1 +
 drivers/usb/phy/Makefile  |   44 +++++++++++
 drivers/usb/phy/twl4030.c |  189 +++++++++++++++++++++++++++++++++++++++++++++
 include/twl4030.h         |  143 ++++++++++++++++++++++++++++++----
 4 files changed, 362 insertions(+), 15 deletions(-)
 create mode 100644 drivers/usb/phy/Makefile
 create mode 100644 drivers/usb/phy/twl4030.c

diff --git a/Makefile b/Makefile
index 356ca29..7ceb066 100644
--- a/Makefile
+++ b/Makefile
@@ -243,6 +243,7 @@ LIBS += drivers/twserial/libtws.a
 LIBS += drivers/usb/gadget/libusb_gadget.a
 LIBS += drivers/usb/host/libusb_host.a
 LIBS += drivers/usb/musb/libusb_musb.a
+LIBS += drivers/usb/phy/libusb_phy.a
 LIBS += drivers/video/libvideo.a
 LIBS += drivers/watchdog/libwatchdog.a
 LIBS += common/libcommon.a
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
new file mode 100644
index 0000000..200b907
--- /dev/null
+++ b/drivers/usb/phy/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2009 Wind River Systems, Inc.
+# Tom Rix <Tom.Rix@windriver.com>
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libusb_phy.a
+
+COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
+COBJS-y := twl4030.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c
new file mode 100644
index 0000000..54d2e61
--- /dev/null
+++ b/drivers/usb/phy/twl4030.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * This is file is based on
+ * repository git.gitorious.org/u-boot-omap3/mainline.git,
+ * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
+ *
+ * This is the unique part of its copyright :
+ *
+ * ------------------------------------------------------------------------
+ *
+ *  * (C) Copyright 2009 Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
+ * Copyright (C) 2004-2007 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * Author: Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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
+ */
+
+#include <twl4030.h>
+
+/* Defines for bits in registers */
+#define OPMODE_MASK		(3 << 3)
+#define XCVRSELECT_MASK		(3 << 0)
+#define CARKITMODE		(1 << 2)
+#define OTG_ENAB		(1 << 5)
+#define PHYPWD			(1 << 0)
+#define CLOCKGATING_EN		(1 << 2)
+#define CLK32K_EN		(1 << 1)
+#define REQ_PHY_DPLL_CLK	(1 << 0)
+#define PHY_DPLL_CLK		(1 << 0)
+
+static int twl4030_usb_write(u8 address, u8 data)
+{
+	int ret;
+
+	ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, data, address);
+	if (ret != 0)
+		printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
+
+	return ret;
+}
+
+static int twl4030_usb_read(u8 address)
+{
+	u8 data;
+	int ret;
+
+	ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, &data, address);
+	if (ret == 0)
+		ret = data;
+	else
+		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
+
+	return ret;
+}
+
+static void twl4030_usb_ldo_init(void)
+{
+	/* Enable writing to power configuration registers */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0xC0,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x0C,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+
+	/* put VUSB3V1 LDO in active state */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB_DEDICATED2);
+
+	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x14,
+			     TWL4030_PM_RECEIVER_VUSB_DEDICATED1);
+
+	/* turn on 3.1V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB3V1_TYPE);
+
+	/* turn on 1.5V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB1V5_TYPE);
+
+	/* turn on 1.8V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB1V8_TYPE);
+
+	/* disable access to power configuration registers */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x00,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+}
+
+static void twl4030_phy_power(void)
+{
+	u8 pwr, clk;
+
+	/* Power the PHY */
+	pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
+	pwr &= ~PHYPWD;
+	twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
+	/* Enable clocks */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk |= CLOCKGATING_EN | CLK32K_EN;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+}
+
+/*
+ * Initiaze the ULPI interface
+ * ULPI : Universal Transceiver Macrocell Low Pin Interface
+ * An interface between the USB link controller like musb and the
+ * the PHY or transceiver that drives the actual bus.
+ */
+int twl4030_usb_ulpi_init(void)
+{
+	long timeout = 1000 * 1000; /* 1 sec */;
+	u8 clk, sts, pwr;
+
+	/* twl4030 ldo init */
+	twl4030_usb_ldo_init();
+
+	/* Enable the twl4030 phy */
+	twl4030_phy_power();
+
+	/* Enable DPLL to access PHY registers over I2C */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk |= REQ_PHY_DPLL_CLK;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+
+	/* Check if the PHY DPLL is locked */
+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+	while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
+		udelay(10);
+		sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+		timeout -= 10;
+	}
+
+	/* Final check */
+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+	if (!(sts & PHY_DPLL_CLK)) {
+		printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
+		return -1;
+	}
+
+	/*
+	 * There are two circuit blocks attached to the PHY,
+	 * Carkit and USB OTG.  Disable Carkit and enable USB OTG
+	 */
+	twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
+	pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
+	pwr |= OTG_ENAB;
+	twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
+
+	/* Clear the opmode bits to ensure normal encode */
+	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
+
+	/* Clear the xcvrselect bits to enable the high speed transeiver */
+	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
+
+	/* Let ULPI control the DPLL clock */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk &= ~REQ_PHY_DPLL_CLK;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+
+	return 0;
+}
diff --git a/include/twl4030.h b/include/twl4030.h
index f260ecb..feaec47 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -342,21 +342,129 @@
 #define TWL4030_KEYPAD_CTRL_SOFT_NRST			(1 << 0)
 
 /* USB */
-#define TWL4030_USB_FUNC_CTRL				(0x04)
-#define TWL4030_USB_OPMODE_MASK				(3 << 3)
-#define TWL4030_USB_XCVRSELECT_MASK			(3 << 0)
-#define TWL4030_USB_IFC_CTRL				(0x07)
-#define TWL4030_USB_CARKITMODE				(1 << 2)
-#define TWL4030_USB_POWER_CTRL				(0xAC)
-#define TWL4030_USB_OTG_ENAB				(1 << 5)
-#define TWL4030_USB_PHY_PWR_CTRL			(0xFD)
-#define TWL4030_USB_PHYPWD				(1 << 0)
-#define TWL4030_USB_PHY_CLK_CTRL			(0xFE)
-#define TWL4030_USB_CLOCKGATING_EN			(1 << 2)
-#define TWL4030_USB_CLK32K_EN				(1 << 1)
-#define TWL4030_USB_REQ_PHY_DPLL_CLK			(1 << 0)
-#define TWL4030_USB_PHY_CLK_CTRL_STS			(0xFF)
-#define TWL4030_USB_PHY_DPLL_CLK			(1 << 0)
+#define TWL4030_USB_VENDOR_ID_LO			0x00
+#define TWL4030_USB_VENDOR_ID_HI			0x01
+#define TWL4030_USB_PRODUCT_ID_LO			0x02
+#define TWL4030_USB_PRODUCT_ID_HI			0x03
+#define TWL4030_USB_FUNC_CTRL				0x04
+#define TWL4030_USB_FUNC_CTRL_SET			0x05
+#define TWL4030_USB_FUNC_CTRL_CLR			0x06
+#define TWL4030_USB_IFC_CTRL				0x07
+#define TWL4030_USB_IFC_CTRL_SET			0x08
+#define TWL4030_USB_IFC_CTRL_CLR			0x09
+#define TWL4030_USB_OTG_CTRL				0x0A
+#define TWL4030_USB_OTG_CTRL_SET			0x0B
+#define TWL4030_USB_OTG_CTRL_CLR			0x0C
+#define TWL4030_USB_USB_INT_EN_RISE			0x0D
+#define TWL4030_USB_USB_INT_EN_RISE_SET			0x0E
+#define TWL4030_USB_USB_INT_EN_RISE_CLR			0x0F
+#define TWL4030_USB_USB_INT_EN_FALL			0x10
+#define TWL4030_USB_USB_INT_EN_FALL_SET			0x11
+#define TWL4030_USB_USB_INT_EN_FALL_CLR			0x12
+#define TWL4030_USB_USB_INT_STS				0x13
+#define TWL4030_USB_USB_INT_LATCH			0x14
+#define TWL4030_USB_DEBUG				0x15
+#define TWL4030_USB_SCRATCH_REG				0x16
+#define TWL4030_USB_SCRATCH_REG_SET			0x17
+#define TWL4030_USB_SCRATCH_REG_CLR			0x18
+#define TWL4030_USB_CARKIT_CTRL				0x19
+#define TWL4030_USB_CARKIT_CTRL_SET			0x1A
+#define TWL4030_USB_CARKIT_CTRL_CLR			0x1B
+#define TWL4030_USB_CARKIT_INT_DELAY			0x1C
+#define TWL4030_USB_CARKIT_INT_EN			0x1D
+#define TWL4030_USB_CARKIT_INT_EN_SET			0x1E
+#define TWL4030_USB_CARKIT_INT_EN_CLR			0x1F
+#define TWL4030_USB_CARKIT_INT_STS			0x20
+#define TWL4030_USB_CARKIT_INT_LATCH			0x21
+#define TWL4030_USB_CARKIT_PLS_CTRL			0x22
+#define TWL4030_USB_CARKIT_PLS_CTRL_SET			0x23
+#define TWL4030_USB_CARKIT_PLS_CTRL_CLR			0x24
+#define TWL4030_USB_TRANS_POS_WIDTH			0x25
+#define TWL4030_USB_TRANS_NEG_WIDTH			0x26
+#define TWL4030_USB_RCV_PLTY_RECOVERY			0x27
+#define TWL4030_USB_MCPC_CTRL				0x30
+#define TWL4030_USB_MCPC_CTRL_SET			0x31
+#define TWL4030_USB_MCPC_CTRL_CLR			0x32
+#define TWL4030_USB_MCPC_IO_CTRL			0x33
+#define TWL4030_USB_MCPC_IO_CTRL_SET			0x34
+#define TWL4030_USB_MCPC_IO_CTRL_CLR			0x35
+#define TWL4030_USB_MCPC_CTRL2				0x36
+#define TWL4030_USB_MCPC_CTRL2_SET			0x37
+#define TWL4030_USB_MCPC_CTRL2_CLR			0x38
+#define TWL4030_USB_OTHER_FUNC_CTRL			0x80
+#define TWL4030_USB_OTHER_FUNC_CTRL_SET			0x81
+#define TWL4030_USB_OTHER_FUNC_CTRL_CLR			0x82
+#define TWL4030_USB_OTHER_IFC_CTRL			0x83
+#define TWL4030_USB_OTHER_IFC_CTRL_SET			0x84
+#define TWL4030_USB_OTHER_IFC_CTRL_CLR			0x85
+#define TWL4030_USB_OTHER_INT_EN_RISE_SET		0x87
+#define TWL4030_USB_OTHER_INT_EN_RISE_CLR		0x88
+#define TWL4030_USB_OTHER_INT_EN_FALL			0x89
+#define TWL4030_USB_OTHER_INT_EN_FALL_SET		0x8A
+#define TWL4030_USB_OTHER_INT_EN_FALL_CLR		0x8B
+#define TWL4030_USB_OTHER_INT_STS			0x8C
+#define TWL4030_USB_OTHER_INT_LATCH			0x8D
+#define TWL4030_USB_ID_STATUS				0x96
+#define TWL4030_USB_CARKIT_SM_1_INT_EN			0x97
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_SET		0x98
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_CLR		0x99
+#define TWL4030_USB_CARKIT_SM_1_INT_STS			0x9A
+#define TWL4030_USB_CARKIT_SM_1_INT_LATCH		0x9B
+#define TWL4030_USB_CARKIT_SM_2_INT_EN			0x9C
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_SET		0x9D
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_CLR		0x9E
+#define TWL4030_USB_CARKIT_SM_2_INT_STS			0x9F
+#define TWL4030_USB_CARKIT_SM_2_INT_LATCH		0xA0
+#define TWL4030_USB_CARKIT_SM_CTRL			0xA1
+#define TWL4030_USB_CARKIT_SM_CTRL_SET			0xA2
+#define TWL4030_USB_CARKIT_SM_CTRL_CLR			0xA3
+#define TWL4030_USB_CARKIT_SM_CMD			0xA4
+#define TWL4030_USB_CARKIT_SM_CMD_SET			0xA5
+#define TWL4030_USB_CARKIT_SM_CMD_CLR			0xA6
+#define TWL4030_USB_CARKIT_SM_CMD_STS			0xA7
+#define TWL4030_USB_CARKIT_SM_STATUS			0xA8
+#define TWL4030_USB_CARKIT_SM_ERR_STATUS		0xAA
+#define TWL4030_USB_CARKIT_SM_CTRL_STATE		0xAB
+#define TWL4030_USB_POWER_CTRL				0xAC
+#define TWL4030_USB_POWER_CTRL_SET			0xAD
+#define TWL4030_USB_POWER_CTRL_CLR			0xAE
+#define TWL4030_USB_OTHER_IFC_CTRL2			0xAF
+#define TWL4030_USB_OTHER_IFC_CTRL2_SET			0xB0
+#define TWL4030_USB_OTHER_IFC_CTRL2_CLR			0xB1
+#define TWL4030_USB_REG_CTRL_EN				0xB2
+#define TWL4030_USB_REG_CTRL_EN_SET			0xB3
+#define TWL4030_USB_REG_CTRL_EN_CLR			0xB4
+#define TWL4030_USB_REG_CTRL_ERROR			0xB5
+#define TWL4030_USB_OTHER_FUNC_CTRL2			0xB8
+#define TWL4030_USB_OTHER_FUNC_CTRL2_SET		0xB9
+#define TWL4030_USB_OTHER_FUNC_CTRL2_CLR		0xBA
+#define TWL4030_USB_CARKIT_ANA_CTRL			0xBB
+#define TWL4030_USB_CARKIT_ANA_CTRL_SET			0xBC
+#define TWL4030_USB_CARKIT_ANA_CTRL_CLR			0xBD
+#define TWL4030_USB_VBUS_DEBOUNCE			0xC0
+#define TWL4030_USB_ID_DEBOUNCE				0xC1
+#define TWL4030_USB_TPH_DP_CON_MIN			0xC2
+#define TWL4030_USB_TPH_DP_CON_MAX			0xC3
+#define TWL4030_USB_TCR_DP_CON_MIN			0xC4
+#define TWL4030_USB_TCR_DP_CON_MAX			0xC5
+#define TWL4030_USB_TPH_DP_PD_SHORT			0xC6
+#define TWL4030_USB_TPH_CMD_DLY				0xC7
+#define TWL4030_USB_TPH_DET_RST				0xC8
+#define TWL4030_USB_TPH_AUD_BIAS			0xC9
+#define TWL4030_USB_TCR_UART_DET_MIN			0xCA
+#define TWL4030_USB_TCR_UART_DET_MAX			0xCB
+#define TWL4030_USB_TPH_ID_INT_PW			0xCD
+#define TWL4030_USB_TACC_ID_INT_WAIT			0xCE
+#define TWL4030_USB_TACC_ID_INT_PW			0xCF
+#define TWL4030_USB_TPH_CMD_WAIT			0xD0
+#define TWL4030_USB_TPH_ACK_WAIT			0xD1
+#define TWL4030_USB_TPH_DP_DISC_DET			0xD2
+#define TWL4030_USB_VBAT_TIMER				0xD3
+#define TWL4030_USB_CARKIT_4W_DEBUG			0xE0
+#define TWL4030_USB_CARKIT_5W_DEBUG			0xE1
+#define TWL4030_USB_PHY_PWR_CTRL			0xFD
+#define TWL4030_USB_PHY_CLK_CTRL			0xFE
+#define TWL4030_USB_PHY_CLK_CTRL_STS			0xFF
 
 /*
  * Convience functions to read and write from TWL4030
@@ -398,4 +506,9 @@ void twl4030_power_mmc_init(void);
  */
 void twl4030_led_init(void);
 
+/*
+ * USB
+ */
+int twl4030_usb_ulpi_init(void);
+
 #endif /* TWL4030_H */
-- 
1.6.0.6

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support
  2009-09-06 13:46       ` Tom
@ 2009-09-06 14:58         ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 0 replies; 14+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-09-06 14:58 UTC (permalink / raw)
  To: u-boot

On 08:46 Sun 06 Sep     , Tom wrote:
> Jean-Christophe PLAGNIOL-VILLARD wrote:
> >On 15:12 Fri 04 Sep     , Tom Rix wrote:
> <snip>
> >please add an empty line
> I will take care of all the empty lines.
> 
> >>+	if (ret == 0)
> >>+		ret = data;
> >>+	else
> >>+		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
> >>+
> >>+	return ret;
> >why not this and avoid the copy of data
> >	if (ret != 0) {
> >		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
> >		return ret;
> >	}
> >
> >	return data;
> >}
> >
> In general I rather have only one exit point from a function.
> This makes tracing execution easier.
ok
> 
> >>+	/* Check if the PHY DPLL is locked */
> >>+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> >>+	while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
> >>+		udelay(10);
> >>+		sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> >>+		timeout -= 10;
> >>+	}
> >why not set time to 100 * 1000
> >	and just decrease by 1
> Yes.
> 
> >make some enums by group of function will be better as it simplify the code
> >>+#define TWL4030_USB_VENDOR_ID_LO			0x00
> >>+#define TWL4030_USB_VENDOR_ID_HI			0x01
> I see your point, but this is how they are defined in a twl4030 spec.
> This way makes it easy to look up #define in the spec.
> Just remove the prefix.
> >>+#define TWL4030_USB_PRODUCT_ID_LO			0x02
> >>+#define TWL4030_USB_PRODUCT_ID_HI			0x03
ok fine

Best Regards,
J.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support
  2009-09-05  0:02     ` Jean-Christophe PLAGNIOL-VILLARD
@ 2009-09-06 13:46       ` Tom
  2009-09-06 14:58         ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 14+ messages in thread
From: Tom @ 2009-09-06 13:46 UTC (permalink / raw)
  To: u-boot

Jean-Christophe PLAGNIOL-VILLARD wrote:
> On 15:12 Fri 04 Sep     , Tom Rix wrote:
>   
<snip>
>>     
> please add an empty line
>   
I will take care of all the empty lines.

>> +	if (ret == 0)
>> +		ret = data;
>> +	else
>> +		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
>> +
>> +	return ret;
>>     
> why not this and avoid the copy of data
> 	if (ret != 0) {
> 		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
> 		return ret;
> 	}
>
> 	return data;
> }
>
>   
In general I rather have only one exit point from a function.
This makes tracing execution easier.

>> +	/* Check if the PHY DPLL is locked */
>> +	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
>> +	while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
>> +		udelay(10);
>> +		sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
>> +		timeout -= 10;
>> +	}
>>     
> why not set time to 100 * 1000
> 	and just decrease by 1
>   
Yes.

> make some enums by group of function will be better as it simplify the code
>   
>> +#define TWL4030_USB_VENDOR_ID_LO			0x00
>> +#define TWL4030_USB_VENDOR_ID_HI			0x01
>>     
I see your point, but this is how they are defined in a twl4030 spec.
This way makes it easy to look up #define in the spec.
Just remove the prefix.
>> +#define TWL4030_USB_PRODUCT_ID_LO			0x02
>> +#define TWL4030_USB_PRODUCT_ID_HI			0x03
>>     
Tom
>
> Best Regards,
> J.
>   

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support
  2009-09-04 20:12   ` [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support Tom Rix
@ 2009-09-05  0:02     ` Jean-Christophe PLAGNIOL-VILLARD
  2009-09-06 13:46       ` Tom
  0 siblings, 1 reply; 14+ messages in thread
From: Jean-Christophe PLAGNIOL-VILLARD @ 2009-09-05  0:02 UTC (permalink / raw)
  To: u-boot

On 15:12 Fri 04 Sep     , Tom Rix wrote:
> The twl4030 provides a PHY device for connecting a link device,
> like musb, to physical connection.
> 
> This change adds the twl4030 usb registers and functions for
> initializing the PHY as required by omap3.
> 
> Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
> ---
>  Makefile                  |    1 +
>  drivers/usb/phy/Makefile  |   44 +++++++++++
>  drivers/usb/phy/twl4030.c |  184 +++++++++++++++++++++++++++++++++++++++++++++
>  include/twl4030.h         |  143 +++++++++++++++++++++++++++++++----
>  4 files changed, 357 insertions(+), 15 deletions(-)
>  create mode 100644 drivers/usb/phy/Makefile
>  create mode 100644 drivers/usb/phy/twl4030.c
> 
> diff --git a/Makefile b/Makefile
> index 329e0f5..dcaa1dc 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -241,6 +241,7 @@ LIBS += drivers/twserial/libtws.a
>  LIBS += drivers/usb/gadget/libusb_gadget.a
>  LIBS += drivers/usb/host/libusb_host.a
>  LIBS += drivers/usb/musb/libusb_musb.a
> +LIBS += drivers/usb/phy/libusb_phy.a
>  LIBS += drivers/video/libvideo.a
>  LIBS += drivers/watchdog/libwatchdog.a
>  LIBS += common/libcommon.a
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> new file mode 100644
> index 0000000..200b907
> --- /dev/null
> +++ b/drivers/usb/phy/Makefile
> @@ -0,0 +1,44 @@
> +#
> +# Copyright (c) 2009 Wind River Systems, Inc.
> +# Tom Rix <Tom.Rix@windriver.com>
> +#
> +# 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
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB	:= $(obj)libusb_phy.a
> +
> +COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
> +COBJS-y := twl4030.o
> +
> +COBJS	:= $(COBJS-y)
> +SRCS	:= $(COBJS:.o=.c)
> +OBJS	:= $(addprefix $(obj),$(COBJS))
> +
> +all:	$(LIB)
> +
> +$(LIB):	$(obj).depend $(OBJS)
> +	$(AR) $(ARFLAGS) $@ $(OBJS)
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c
> new file mode 100644
> index 0000000..32f1df3
> --- /dev/null
> +++ b/drivers/usb/phy/twl4030.c
> @@ -0,0 +1,184 @@
> +/*
> + * Copyright (c) 2009 Wind River Systems, Inc.
> + * Tom Rix <Tom.Rix@windriver.com>
> + *
> + * This is file is based on
> + * repository git.gitorious.org/u-boot-omap3/mainline.git,
> + * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
> + *
> + * This is the unique part of its copyright :
> + *
> + * ------------------------------------------------------------------------
> + *
> + *  * (C) Copyright 2009 Atin Malaviya (atin.malaviya at gmail.com)
> + *
> + * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
> + * Copyright (C) 2004-2007 Texas Instruments
> + * Copyright (C) 2008 Nokia Corporation
> + * Contact: Felipe Balbi <felipe.balbi@nokia.com>
> + *
> + * Author: Atin Malaviya (atin.malaviya at gmail.com)
> + *
> + * ------------------------------------------------------------------------
> + *
> + * 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
> + */
> +
> +#include <twl4030.h>
> +
> +/* Defines for bits in registers */
> +#define OPMODE_MASK		(3 << 3)
> +#define XCVRSELECT_MASK		(3 << 0)
> +#define CARKITMODE		(1 << 2)
> +#define OTG_ENAB		(1 << 5)
> +#define PHYPWD			(1 << 0)
> +#define CLOCKGATING_EN		(1 << 2)
> +#define CLK32K_EN		(1 << 1)
> +#define REQ_PHY_DPLL_CLK	(1 << 0)
> +#define PHY_DPLL_CLK		(1 << 0)
> +
> +static int twl4030_usb_write(u8 address, u8 data)
> +{
> +	int ret;
please add an empty line
> +	ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, data, address);
> +	if (ret != 0)
> +		printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
> +
> +	return ret;
> +}
> +
> +static int twl4030_usb_read(u8 address)
> +{
> +	u8 data;
> +	int ret;
please add an empty line
> +	ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, &data, address);

> +	if (ret == 0)
> +		ret = data;
> +	else
> +		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
> +
> +	return ret;
why not this and avoid the copy of data
	if (ret != 0) {
		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
		return ret;
	}

	return data;
}

> +
> +static void twl4030_phy_power(void)
> +{
> +	u8 pwr, clk;
please add an empty line
> +	/* Power the PHY */
> +	pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
> +	pwr &= ~PHYPWD;
> +	twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
please add an empty line to make it more readable
> +	/* Enable clocks */
> +	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
> +	clk |= CLOCKGATING_EN | CLK32K_EN;
> +	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
> +}
> +
> +/*
> + * Initiaze the ULPI interface
> + * ULPI : Universal Transceiver Macrocell Low Pin Interface
> + * An interface between the USB link controller like musb and the
> + * the PHY or transceiver that drives the actual bus.
> + */
> +int twl4030_usb_ulpi_init(void)
> +{
> +	long timeout = 1000 * 1000; /* 1 sec */;
> +	u8 clk, sts, pwr;
> +
> +	/* twl4030 ldo init */
> +	twl4030_usb_ldo_init();
> +
> +	/* Enable the twl4030 phy */
> +	twl4030_phy_power();
> +
> +	/* Enable DPLL to access PHY registers over I2C */
> +	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
> +	clk |= REQ_PHY_DPLL_CLK;
> +	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
> +
> +	/* Check if the PHY DPLL is locked */
> +	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> +	while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
> +		udelay(10);
> +		sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> +		timeout -= 10;
> +	}
why not set time to 100 * 1000
	and just decrease by 1
> +
> +	/* Final check */
> +	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
> +	if (!(sts & PHY_DPLL_CLK)) {
> +		printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
> +		return -1;
> +	}
> +
> +	/*
> +	 * There are two circuit blocks attached to the PHY,
> +	 * Carkit and USB OTG.  Disable Carkit and enable USB OTG
> +	 */
> +	twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
> +	pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
> +	pwr |= OTG_ENAB;
> +	twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
please add an empty line to make it more readable
> +	/* Clear the opmode bits to ensure normal encode */
> +	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
please add an empty line to make it more readable
> +	/* Clear the xcvrselect bits to enable the high speed transeiver */
> +	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
> +
> +	/* Let ULPI control the DPLL clock */
> +	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
> +	clk &= ~REQ_PHY_DPLL_CLK;
> +	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
> +
> +	return 0;
> +}
> diff --git a/include/twl4030.h b/include/twl4030.h
> index f260ecb..feaec47 100644
> --- a/include/twl4030.h
> +++ b/include/twl4030.h
> @@ -342,21 +342,129 @@
>  #define TWL4030_KEYPAD_CTRL_SOFT_NRST			(1 << 0)
>  
>  /* USB */
> -#define TWL4030_USB_FUNC_CTRL				(0x04)
> -#define TWL4030_USB_OPMODE_MASK				(3 << 3)
> -#define TWL4030_USB_XCVRSELECT_MASK			(3 << 0)
> -#define TWL4030_USB_IFC_CTRL				(0x07)
> -#define TWL4030_USB_CARKITMODE				(1 << 2)
> -#define TWL4030_USB_POWER_CTRL				(0xAC)
> -#define TWL4030_USB_OTG_ENAB				(1 << 5)
> -#define TWL4030_USB_PHY_PWR_CTRL			(0xFD)
> -#define TWL4030_USB_PHYPWD				(1 << 0)
> -#define TWL4030_USB_PHY_CLK_CTRL			(0xFE)
> -#define TWL4030_USB_CLOCKGATING_EN			(1 << 2)
> -#define TWL4030_USB_CLK32K_EN				(1 << 1)
> -#define TWL4030_USB_REQ_PHY_DPLL_CLK			(1 << 0)
> -#define TWL4030_USB_PHY_CLK_CTRL_STS			(0xFF)
> -#define TWL4030_USB_PHY_DPLL_CLK			(1 << 0)
make some enums by group of function will be better as it simplify the code
> +#define TWL4030_USB_VENDOR_ID_LO			0x00
> +#define TWL4030_USB_VENDOR_ID_HI			0x01
> +#define TWL4030_USB_PRODUCT_ID_LO			0x02
> +#define TWL4030_USB_PRODUCT_ID_HI			0x03
> +#define TWL4030_USB_FUNC_CTRL				0x04
> +#define TWL4030_USB_FUNC_CTRL_SET			0x05
> +#define TWL4030_USB_FUNC_CTRL_CLR			0x06
> +#define TWL4030_USB_IFC_CTRL				0x07
> +#define TWL4030_USB_IFC_CTRL_SET			0x08
> +#define TWL4030_USB_IFC_CTRL_CLR			0x09
> +#define TWL4030_USB_OTG_CTRL				0x0A
> +#define TWL4030_USB_OTG_CTRL_SET			0x0B
> +#define TWL4030_USB_OTG_CTRL_CLR			0x0C
> +#define TWL4030_USB_USB_INT_EN_RISE			0x0D
> +#define TWL4030_USB_USB_INT_EN_RISE_SET			0x0E
> +#define TWL4030_USB_USB_INT_EN_RISE_CLR			0x0F
> +#define TWL4030_USB_USB_INT_EN_FALL			0x10
> +#define TWL4030_USB_USB_INT_EN_FALL_SET			0x11
> +#define TWL4030_USB_USB_INT_EN_FALL_CLR			0x12
> +#define TWL4030_USB_USB_INT_STS				0x13
> +#define TWL4030_USB_USB_INT_LATCH			0x14
> +#define TWL4030_USB_DEBUG				0x15
> +#define TWL4030_USB_SCRATCH_REG				0x16
> +#define TWL4030_USB_SCRATCH_REG_SET			0x17
> +#define TWL4030_USB_SCRATCH_REG_CLR			0x18
> +#define TWL4030_USB_CARKIT_CTRL				0x19
> +#define TWL4030_USB_CARKIT_CTRL_SET			0x1A
> +#define TWL4030_USB_CARKIT_CTRL_CLR			0x1B
> +#define TWL4030_USB_CARKIT_INT_DELAY			0x1C
> +#define TWL4030_USB_CARKIT_INT_EN			0x1D
> +#define TWL4030_USB_CARKIT_INT_EN_SET			0x1E
> +#define TWL4030_USB_CARKIT_INT_EN_CLR			0x1F
> +#define TWL4030_USB_CARKIT_INT_STS			0x20
> +#define TWL4030_USB_CARKIT_INT_LATCH			0x21
> +#define TWL4030_USB_CARKIT_PLS_CTRL			0x22
> +#define TWL4030_USB_CARKIT_PLS_CTRL_SET			0x23
> +#define TWL4030_USB_CARKIT_PLS_CTRL_CLR			0x24
> +#define TWL4030_USB_TRANS_POS_WIDTH			0x25
> +#define TWL4030_USB_TRANS_NEG_WIDTH			0x26
> +#define TWL4030_USB_RCV_PLTY_RECOVERY			0x27
> +#define TWL4030_USB_MCPC_CTRL				0x30
> +#define TWL4030_USB_MCPC_CTRL_SET			0x31
> +#define TWL4030_USB_MCPC_CTRL_CLR			0x32
> +#define TWL4030_USB_MCPC_IO_CTRL			0x33
> +#define TWL4030_USB_MCPC_IO_CTRL_SET			0x34

Best Regards,
J.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support
  2009-09-04 20:12 ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup Tom Rix
@ 2009-09-04 20:12   ` Tom Rix
  2009-09-05  0:02     ` Jean-Christophe PLAGNIOL-VILLARD
  0 siblings, 1 reply; 14+ messages in thread
From: Tom Rix @ 2009-09-04 20:12 UTC (permalink / raw)
  To: u-boot

The twl4030 provides a PHY device for connecting a link device,
like musb, to physical connection.

This change adds the twl4030 usb registers and functions for
initializing the PHY as required by omap3.

Signed-off-by: Tom Rix <Tom.Rix@windriver.com>
---
 Makefile                  |    1 +
 drivers/usb/phy/Makefile  |   44 +++++++++++
 drivers/usb/phy/twl4030.c |  184 +++++++++++++++++++++++++++++++++++++++++++++
 include/twl4030.h         |  143 +++++++++++++++++++++++++++++++----
 4 files changed, 357 insertions(+), 15 deletions(-)
 create mode 100644 drivers/usb/phy/Makefile
 create mode 100644 drivers/usb/phy/twl4030.c

diff --git a/Makefile b/Makefile
index 329e0f5..dcaa1dc 100644
--- a/Makefile
+++ b/Makefile
@@ -241,6 +241,7 @@ LIBS += drivers/twserial/libtws.a
 LIBS += drivers/usb/gadget/libusb_gadget.a
 LIBS += drivers/usb/host/libusb_host.a
 LIBS += drivers/usb/musb/libusb_musb.a
+LIBS += drivers/usb/phy/libusb_phy.a
 LIBS += drivers/video/libvideo.a
 LIBS += drivers/watchdog/libwatchdog.a
 LIBS += common/libcommon.a
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
new file mode 100644
index 0000000..200b907
--- /dev/null
+++ b/drivers/usb/phy/Makefile
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2009 Wind River Systems, Inc.
+# Tom Rix <Tom.Rix@windriver.com>
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	:= $(obj)libusb_phy.a
+
+COBJS-$(CONFIG_TWL4030_USB) += twl4030.o
+COBJS-y := twl4030.o
+
+COBJS	:= $(COBJS-y)
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+all:	$(LIB)
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(AR) $(ARFLAGS) $@ $(OBJS)
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/drivers/usb/phy/twl4030.c b/drivers/usb/phy/twl4030.c
new file mode 100644
index 0000000..32f1df3
--- /dev/null
+++ b/drivers/usb/phy/twl4030.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2009 Wind River Systems, Inc.
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * This is file is based on
+ * repository git.gitorious.org/u-boot-omap3/mainline.git,
+ * branch omap3-dev-usb, file drivers/usb/gadget/twl4030_usb.c
+ *
+ * This is the unique part of its copyright :
+ *
+ * ------------------------------------------------------------------------
+ *
+ *  * (C) Copyright 2009 Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * Based on: twl4030_usb.c in linux 2.6 (drivers/i2c/chips/twl4030_usb.c)
+ * Copyright (C) 2004-2007 Texas Instruments
+ * Copyright (C) 2008 Nokia Corporation
+ * Contact: Felipe Balbi <felipe.balbi@nokia.com>
+ *
+ * Author: Atin Malaviya (atin.malaviya at gmail.com)
+ *
+ * ------------------------------------------------------------------------
+ *
+ * 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
+ */
+
+#include <twl4030.h>
+
+/* Defines for bits in registers */
+#define OPMODE_MASK		(3 << 3)
+#define XCVRSELECT_MASK		(3 << 0)
+#define CARKITMODE		(1 << 2)
+#define OTG_ENAB		(1 << 5)
+#define PHYPWD			(1 << 0)
+#define CLOCKGATING_EN		(1 << 2)
+#define CLK32K_EN		(1 << 1)
+#define REQ_PHY_DPLL_CLK	(1 << 0)
+#define PHY_DPLL_CLK		(1 << 0)
+
+static int twl4030_usb_write(u8 address, u8 data)
+{
+	int ret;
+	ret = twl4030_i2c_write_u8(TWL4030_CHIP_USB, data, address);
+	if (ret != 0)
+		printf("TWL4030:USB:Write[0x%x] Error %d\n", address, ret);
+
+	return ret;
+}
+
+static int twl4030_usb_read(u8 address)
+{
+	u8 data;
+	int ret;
+	ret = twl4030_i2c_read_u8(TWL4030_CHIP_USB, &data, address);
+	if (ret == 0)
+		ret = data;
+	else
+		printf("TWL4030:USB:Read[0x%x] Error %d\n", address, ret);
+
+	return ret;
+}
+
+static void twl4030_usb_ldo_init(void)
+{
+	/* Enable writing to power configuration registers */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0xC0,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x0C,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+
+	/* put VUSB3V1 LDO in active state */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB_DEDICATED2);
+
+	/* input to VUSB3V1 LDO is from VBAT, not VBUS */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x14,
+			     TWL4030_PM_RECEIVER_VUSB_DEDICATED1);
+
+	/* turn on 3.1V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB3V1_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB3V1_TYPE);
+
+	/* turn on 1.5V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB1V5_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB1V5_TYPE);
+
+	/* turn on 1.8V regulator */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x20,
+			     TWL4030_PM_RECEIVER_VUSB1V8_DEV_GRP);
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_RECEIVER, 0x00,
+			     TWL4030_PM_RECEIVER_VUSB1V8_TYPE);
+
+	/* disable access to power configuration registers */
+	twl4030_i2c_write_u8(TWL4030_CHIP_PM_MASTER, 0x00,
+			     TWL4030_PM_MASTER_PROTECT_KEY);
+}
+
+static void twl4030_phy_power(void)
+{
+	u8 pwr, clk;
+	/* Power the PHY */
+	pwr = twl4030_usb_read(TWL4030_USB_PHY_PWR_CTRL);
+	pwr &= ~PHYPWD;
+	twl4030_usb_write(TWL4030_USB_PHY_PWR_CTRL, pwr);
+	/* Enable clocks */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk |= CLOCKGATING_EN | CLK32K_EN;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+}
+
+/*
+ * Initiaze the ULPI interface
+ * ULPI : Universal Transceiver Macrocell Low Pin Interface
+ * An interface between the USB link controller like musb and the
+ * the PHY or transceiver that drives the actual bus.
+ */
+int twl4030_usb_ulpi_init(void)
+{
+	long timeout = 1000 * 1000; /* 1 sec */;
+	u8 clk, sts, pwr;
+
+	/* twl4030 ldo init */
+	twl4030_usb_ldo_init();
+
+	/* Enable the twl4030 phy */
+	twl4030_phy_power();
+
+	/* Enable DPLL to access PHY registers over I2C */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk |= REQ_PHY_DPLL_CLK;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+
+	/* Check if the PHY DPLL is locked */
+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+	while (!(sts & PHY_DPLL_CLK) && 0 < timeout) {
+		udelay(10);
+		sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+		timeout -= 10;
+	}
+
+	/* Final check */
+	sts = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL_STS);
+	if (!(sts & PHY_DPLL_CLK)) {
+		printf("Error:TWL4030:USB Timeout setting PHY DPLL clock\n");
+		return -1;
+	}
+
+	/*
+	 * There are two circuit blocks attached to the PHY,
+	 * Carkit and USB OTG.  Disable Carkit and enable USB OTG
+	 */
+	twl4030_usb_write(TWL4030_USB_IFC_CTRL_CLR, CARKITMODE);
+	pwr = twl4030_usb_read(TWL4030_USB_POWER_CTRL);
+	pwr |= OTG_ENAB;
+	twl4030_usb_write(TWL4030_USB_POWER_CTRL_SET, pwr);
+	/* Clear the opmode bits to ensure normal encode */
+	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, OPMODE_MASK);
+	/* Clear the xcvrselect bits to enable the high speed transeiver */
+	twl4030_usb_write(TWL4030_USB_FUNC_CTRL_CLR, XCVRSELECT_MASK);
+
+	/* Let ULPI control the DPLL clock */
+	clk = twl4030_usb_read(TWL4030_USB_PHY_CLK_CTRL);
+	clk &= ~REQ_PHY_DPLL_CLK;
+	twl4030_usb_write(TWL4030_USB_PHY_CLK_CTRL, clk);
+
+	return 0;
+}
diff --git a/include/twl4030.h b/include/twl4030.h
index f260ecb..feaec47 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -342,21 +342,129 @@
 #define TWL4030_KEYPAD_CTRL_SOFT_NRST			(1 << 0)
 
 /* USB */
-#define TWL4030_USB_FUNC_CTRL				(0x04)
-#define TWL4030_USB_OPMODE_MASK				(3 << 3)
-#define TWL4030_USB_XCVRSELECT_MASK			(3 << 0)
-#define TWL4030_USB_IFC_CTRL				(0x07)
-#define TWL4030_USB_CARKITMODE				(1 << 2)
-#define TWL4030_USB_POWER_CTRL				(0xAC)
-#define TWL4030_USB_OTG_ENAB				(1 << 5)
-#define TWL4030_USB_PHY_PWR_CTRL			(0xFD)
-#define TWL4030_USB_PHYPWD				(1 << 0)
-#define TWL4030_USB_PHY_CLK_CTRL			(0xFE)
-#define TWL4030_USB_CLOCKGATING_EN			(1 << 2)
-#define TWL4030_USB_CLK32K_EN				(1 << 1)
-#define TWL4030_USB_REQ_PHY_DPLL_CLK			(1 << 0)
-#define TWL4030_USB_PHY_CLK_CTRL_STS			(0xFF)
-#define TWL4030_USB_PHY_DPLL_CLK			(1 << 0)
+#define TWL4030_USB_VENDOR_ID_LO			0x00
+#define TWL4030_USB_VENDOR_ID_HI			0x01
+#define TWL4030_USB_PRODUCT_ID_LO			0x02
+#define TWL4030_USB_PRODUCT_ID_HI			0x03
+#define TWL4030_USB_FUNC_CTRL				0x04
+#define TWL4030_USB_FUNC_CTRL_SET			0x05
+#define TWL4030_USB_FUNC_CTRL_CLR			0x06
+#define TWL4030_USB_IFC_CTRL				0x07
+#define TWL4030_USB_IFC_CTRL_SET			0x08
+#define TWL4030_USB_IFC_CTRL_CLR			0x09
+#define TWL4030_USB_OTG_CTRL				0x0A
+#define TWL4030_USB_OTG_CTRL_SET			0x0B
+#define TWL4030_USB_OTG_CTRL_CLR			0x0C
+#define TWL4030_USB_USB_INT_EN_RISE			0x0D
+#define TWL4030_USB_USB_INT_EN_RISE_SET			0x0E
+#define TWL4030_USB_USB_INT_EN_RISE_CLR			0x0F
+#define TWL4030_USB_USB_INT_EN_FALL			0x10
+#define TWL4030_USB_USB_INT_EN_FALL_SET			0x11
+#define TWL4030_USB_USB_INT_EN_FALL_CLR			0x12
+#define TWL4030_USB_USB_INT_STS				0x13
+#define TWL4030_USB_USB_INT_LATCH			0x14
+#define TWL4030_USB_DEBUG				0x15
+#define TWL4030_USB_SCRATCH_REG				0x16
+#define TWL4030_USB_SCRATCH_REG_SET			0x17
+#define TWL4030_USB_SCRATCH_REG_CLR			0x18
+#define TWL4030_USB_CARKIT_CTRL				0x19
+#define TWL4030_USB_CARKIT_CTRL_SET			0x1A
+#define TWL4030_USB_CARKIT_CTRL_CLR			0x1B
+#define TWL4030_USB_CARKIT_INT_DELAY			0x1C
+#define TWL4030_USB_CARKIT_INT_EN			0x1D
+#define TWL4030_USB_CARKIT_INT_EN_SET			0x1E
+#define TWL4030_USB_CARKIT_INT_EN_CLR			0x1F
+#define TWL4030_USB_CARKIT_INT_STS			0x20
+#define TWL4030_USB_CARKIT_INT_LATCH			0x21
+#define TWL4030_USB_CARKIT_PLS_CTRL			0x22
+#define TWL4030_USB_CARKIT_PLS_CTRL_SET			0x23
+#define TWL4030_USB_CARKIT_PLS_CTRL_CLR			0x24
+#define TWL4030_USB_TRANS_POS_WIDTH			0x25
+#define TWL4030_USB_TRANS_NEG_WIDTH			0x26
+#define TWL4030_USB_RCV_PLTY_RECOVERY			0x27
+#define TWL4030_USB_MCPC_CTRL				0x30
+#define TWL4030_USB_MCPC_CTRL_SET			0x31
+#define TWL4030_USB_MCPC_CTRL_CLR			0x32
+#define TWL4030_USB_MCPC_IO_CTRL			0x33
+#define TWL4030_USB_MCPC_IO_CTRL_SET			0x34
+#define TWL4030_USB_MCPC_IO_CTRL_CLR			0x35
+#define TWL4030_USB_MCPC_CTRL2				0x36
+#define TWL4030_USB_MCPC_CTRL2_SET			0x37
+#define TWL4030_USB_MCPC_CTRL2_CLR			0x38
+#define TWL4030_USB_OTHER_FUNC_CTRL			0x80
+#define TWL4030_USB_OTHER_FUNC_CTRL_SET			0x81
+#define TWL4030_USB_OTHER_FUNC_CTRL_CLR			0x82
+#define TWL4030_USB_OTHER_IFC_CTRL			0x83
+#define TWL4030_USB_OTHER_IFC_CTRL_SET			0x84
+#define TWL4030_USB_OTHER_IFC_CTRL_CLR			0x85
+#define TWL4030_USB_OTHER_INT_EN_RISE_SET		0x87
+#define TWL4030_USB_OTHER_INT_EN_RISE_CLR		0x88
+#define TWL4030_USB_OTHER_INT_EN_FALL			0x89
+#define TWL4030_USB_OTHER_INT_EN_FALL_SET		0x8A
+#define TWL4030_USB_OTHER_INT_EN_FALL_CLR		0x8B
+#define TWL4030_USB_OTHER_INT_STS			0x8C
+#define TWL4030_USB_OTHER_INT_LATCH			0x8D
+#define TWL4030_USB_ID_STATUS				0x96
+#define TWL4030_USB_CARKIT_SM_1_INT_EN			0x97
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_SET		0x98
+#define TWL4030_USB_CARKIT_SM_1_INT_EN_CLR		0x99
+#define TWL4030_USB_CARKIT_SM_1_INT_STS			0x9A
+#define TWL4030_USB_CARKIT_SM_1_INT_LATCH		0x9B
+#define TWL4030_USB_CARKIT_SM_2_INT_EN			0x9C
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_SET		0x9D
+#define TWL4030_USB_CARKIT_SM_2_INT_EN_CLR		0x9E
+#define TWL4030_USB_CARKIT_SM_2_INT_STS			0x9F
+#define TWL4030_USB_CARKIT_SM_2_INT_LATCH		0xA0
+#define TWL4030_USB_CARKIT_SM_CTRL			0xA1
+#define TWL4030_USB_CARKIT_SM_CTRL_SET			0xA2
+#define TWL4030_USB_CARKIT_SM_CTRL_CLR			0xA3
+#define TWL4030_USB_CARKIT_SM_CMD			0xA4
+#define TWL4030_USB_CARKIT_SM_CMD_SET			0xA5
+#define TWL4030_USB_CARKIT_SM_CMD_CLR			0xA6
+#define TWL4030_USB_CARKIT_SM_CMD_STS			0xA7
+#define TWL4030_USB_CARKIT_SM_STATUS			0xA8
+#define TWL4030_USB_CARKIT_SM_ERR_STATUS		0xAA
+#define TWL4030_USB_CARKIT_SM_CTRL_STATE		0xAB
+#define TWL4030_USB_POWER_CTRL				0xAC
+#define TWL4030_USB_POWER_CTRL_SET			0xAD
+#define TWL4030_USB_POWER_CTRL_CLR			0xAE
+#define TWL4030_USB_OTHER_IFC_CTRL2			0xAF
+#define TWL4030_USB_OTHER_IFC_CTRL2_SET			0xB0
+#define TWL4030_USB_OTHER_IFC_CTRL2_CLR			0xB1
+#define TWL4030_USB_REG_CTRL_EN				0xB2
+#define TWL4030_USB_REG_CTRL_EN_SET			0xB3
+#define TWL4030_USB_REG_CTRL_EN_CLR			0xB4
+#define TWL4030_USB_REG_CTRL_ERROR			0xB5
+#define TWL4030_USB_OTHER_FUNC_CTRL2			0xB8
+#define TWL4030_USB_OTHER_FUNC_CTRL2_SET		0xB9
+#define TWL4030_USB_OTHER_FUNC_CTRL2_CLR		0xBA
+#define TWL4030_USB_CARKIT_ANA_CTRL			0xBB
+#define TWL4030_USB_CARKIT_ANA_CTRL_SET			0xBC
+#define TWL4030_USB_CARKIT_ANA_CTRL_CLR			0xBD
+#define TWL4030_USB_VBUS_DEBOUNCE			0xC0
+#define TWL4030_USB_ID_DEBOUNCE				0xC1
+#define TWL4030_USB_TPH_DP_CON_MIN			0xC2
+#define TWL4030_USB_TPH_DP_CON_MAX			0xC3
+#define TWL4030_USB_TCR_DP_CON_MIN			0xC4
+#define TWL4030_USB_TCR_DP_CON_MAX			0xC5
+#define TWL4030_USB_TPH_DP_PD_SHORT			0xC6
+#define TWL4030_USB_TPH_CMD_DLY				0xC7
+#define TWL4030_USB_TPH_DET_RST				0xC8
+#define TWL4030_USB_TPH_AUD_BIAS			0xC9
+#define TWL4030_USB_TCR_UART_DET_MIN			0xCA
+#define TWL4030_USB_TCR_UART_DET_MAX			0xCB
+#define TWL4030_USB_TPH_ID_INT_PW			0xCD
+#define TWL4030_USB_TACC_ID_INT_WAIT			0xCE
+#define TWL4030_USB_TACC_ID_INT_PW			0xCF
+#define TWL4030_USB_TPH_CMD_WAIT			0xD0
+#define TWL4030_USB_TPH_ACK_WAIT			0xD1
+#define TWL4030_USB_TPH_DP_DISC_DET			0xD2
+#define TWL4030_USB_VBAT_TIMER				0xD3
+#define TWL4030_USB_CARKIT_4W_DEBUG			0xE0
+#define TWL4030_USB_CARKIT_5W_DEBUG			0xE1
+#define TWL4030_USB_PHY_PWR_CTRL			0xFD
+#define TWL4030_USB_PHY_CLK_CTRL			0xFE
+#define TWL4030_USB_PHY_CLK_CTRL_STS			0xFF
 
 /*
  * Convience functions to read and write from TWL4030
@@ -398,4 +506,9 @@ void twl4030_power_mmc_init(void);
  */
 void twl4030_led_init(void);
 
+/*
+ * USB
+ */
+int twl4030_usb_ulpi_init(void);
+
 #endif /* TWL4030_H */
-- 
1.6.0.4

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2009-09-28 16:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-09-28 16:34 [U-Boot] V2 of OMAP3 USB device Support y at windriver.com
2009-09-28 16:34 ` [U-Boot] [PATCH 1/8] USB Consolidate descriptor definitions y at windriver.com
2009-09-28 16:34   ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup y at windriver.com
2009-09-28 16:34     ` [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support y at windriver.com
2009-09-28 16:34       ` [U-Boot] [PATCH 4/8] OMAP3 Add usb device support y at windriver.com
2009-09-28 16:35         ` [U-Boot] [PATCH 5/8] OMAP3 zoom1 Add usbtty configuration y at windriver.com
2009-09-28 16:35           ` [U-Boot] [PATCH 6/8] OMAP3 beagle " y at windriver.com
2009-09-28 16:35             ` [U-Boot] [PATCH 7/8] USBTTY make some function declarations easier to use y at windriver.com
2009-09-28 16:35               ` [U-Boot] [PATCH 8/8] OMAP3 zoom2 Use usbtty if the debug board is not connected y at windriver.com
  -- strict thread matches above, loose matches on Subject: below --
2009-09-28 16:37 [U-Boot] V2 of OMAP3 USB device Support Tom Rix
2009-09-28 16:37 ` [U-Boot] [PATCH 1/8] USB Consolidate descriptor definitions Tom Rix
2009-09-28 16:37   ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup Tom Rix
2009-09-28 16:37     ` [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support Tom Rix
2009-09-04 20:12 [U-Boot] [PATCH 1/8] USB Consolidate descriptor definitions Tom Rix
2009-09-04 20:12 ` [U-Boot] [PATCH 2/8] USB add macros for debugging usb device setup Tom Rix
2009-09-04 20:12   ` [U-Boot] [PATCH 3/8] TWL4030 Add usb PHY support Tom Rix
2009-09-05  0:02     ` Jean-Christophe PLAGNIOL-VILLARD
2009-09-06 13:46       ` Tom
2009-09-06 14:58         ` Jean-Christophe PLAGNIOL-VILLARD

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.