All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vivek Kutal <vivek.kutal@azingo.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [RFC] PXA27X UDC Support.
Date: Fri, 20 Feb 2009 18:06:13 +0530	[thread overview]
Message-ID: <499EA3BD.9010908@azingo.com> (raw)

Hi all,
        This is the patch for UDC support for PXA27X , it is based on a 
patch previously submitted by Rodolfo Giometti.
--
Regards,
Vivek Kutal


 From 081685ce3c5b80bc439485ec8e1847d85dc7ad70 Mon Sep 17 00:00:00 2001
From: Vivek Kutal <vivek.kutal@azingo.com>
Date: Thu, 19 Feb 2009 17:56:38 +0530
Subject: [PATCH] Support for PXA27X UDC.

Signed-off-by: Vivek Kutal <vivek.kutal@azingo.com>
---
 drivers/usb/Makefile          |    1 +
 drivers/usb/pxa27x_udc_regs.h |  417 ++++++++++++++++++++++++
 drivers/usb/usbdcore_pxa27x.c |  714 
+++++++++++++++++++++++++++++++++++++++++
 include/usbdcore_pxa2xx.h     |   68 ++++
 4 files changed, 1200 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/pxa27x_udc_regs.h
 create mode 100644 drivers/usb/usbdcore_pxa27x.c
 create mode 100644 include/usbdcore_pxa2xx.h

diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index b306a65..0a1886a 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -47,6 +47,7 @@ COBJS-y += usbdcore_ep0.o
 COBJS-$(CONFIG_OMAP1510) += usbdcore_omap1510.o
 COBJS-$(CONFIG_OMAP1610) += usbdcore_omap1510.o
 COBJS-$(CONFIG_MPC885_FAMILY) += usbdcore_mpc8xx.o
+COBJS-$(CONFIG_PXA27X) += usbdcore_pxa27x.o
 endif
 
 COBJS    := $(COBJS-y)
diff --git a/drivers/usb/pxa27x_udc_regs.h b/drivers/usb/pxa27x_udc_regs.h
new file mode 100644
index 0000000..47bf66e
--- /dev/null
+++ b/drivers/usb/pxa27x_udc_regs.h
@@ -0,0 +1,417 @@
+/*
+ *  Taken from linux kernel include/asm-arm/arch-pxa/pxa-regs.h
+ *
+ */
+
+
+#ifndef __PXA27X_UDC_REGS_H
+#define __PXA27X_UDC_REGS_H
+
+/*
+ * USB Device Controller
+ */
+#define UDC_RES1        __REG(0x40600004)  /* UDC Undocumented - 
Reserved1 */
+#define UDC_RES2        __REG(0x40600008)  /* UDC Undocumented - 
Reserved2 */
+#define UDC_RES3        __REG(0x4060000C)  /* UDC Undocumented - 
Reserved3 */
+
+#define UDCCONR_CN            (0x03 << 25)    /* Configuration Number */
+#define UDCCONR_CN_S        (25)
+#define UDCCONR_IN            (0x07 << 22)    /* Interface Number */
+#define UDCCONR_IN_S        (22)
+#define UDCCONR_AISN        (0x07 << 19)    /* Alternate Interface 
Number */
+#define UDCCONR_AISN_S        (19)
+#define UDCCONR_EN            (0x0f << 15)    /* Endpoint Number */
+#define UDCCONR_EN_S        (15)
+#define UDCCONR_ET_S        (13)
+#define UDCCONR_ET_INT        (0x03 << 13)    /*   Interrupt */
+#define UDCCONR_ET_BULK        (0x02 << 13)    /*   Bulk */
+#define UDCCONR_ET_ISO        (0x01 << 13)    /*   Isochronous */
+#define UDCCONR_ET_NU        (0x00 << 13)    /*   Not used */
+#define UDCCONR_ED            (1 << 12)        /* Endpoint Direction */
+#define UDCCONR_MPS            (0x3ff << 2)    /* Maximum Packet Size */
+#define UDCCONR_MPS_S        (2)
+#define UDCCONR_DE            (1 << 1)        /* Double Buffering Enable */
+#define UDCCONR_EE            (1 << 0)        /* Endpoint Enable */
+#define GPDR1_B_USB_DEC_N   (0x01 << 3)
+
+
+#define UDCCRA          __REG(0x40600404) /* Configuration register EPA */
+#define UDCCRB          __REG(0x40600408) /* Configuration register EPB */
+#define UP2OCR            __REG(0x40600020)
+#define UDCWAKEUP        __REG(0x40F00044)
+#define UDCICR0         __REG(0x40600004) /* UDC Interrupt Control 
Register0 */
+#define UDCICR1         __REG(0x40600008) /* UDC Interrupt Control 
Register1 */
+#define UDCISR0            __REG(0x4060000C) /* UDC Interrupt Status 
Register 0 */
+#define UDCISR1         __REG(0x40600010) /* UDC Interrupt Status 
Register 1 */
+
+
+
+#define UDCCR            __REG(0x40600000)  /* UDC Control Register */
+#define UDCCR_UDE        (1 << 0)    /* UDC enable */
+#define UDCCR_UDA        (1 << 1)    /* UDC active */
+#define UDCCR_RSM        (1 << 2)    /* Device resume */
+#define UDCCR_RESIR        (1 << 29)    /* Resume interrupt request */
+#define UDCCR_SUSIR        (1 << 28)    /* Suspend interrupt request */
+#define UDCCR_SM        (1 << 28)    /* Suspend interrupt mask */
+#define UDCCR_RSTIR        (1 << 27)    /* Reset interrupt request */
+#define UDCCR_REM        (1 << 27)    /* Reset interrupt mask */
+#define UDCCR_RM        (1 << 29)    /* resume interrupt mask */
+#define UDCCR_SRM        UDCCR_SM|UDCCR_RM
+
+#define UDCCS0            __REG(0x40600100)  /* UDC Endpoint 0 
Control/Status Register */
+#define UDCCS0_OPR        (1 << 0)    /* OUT packet ready */
+#define UDCCS0_IPR        (1 << 1)    /* IN packet ready */
+#define UDCCS0_FTF        (1 << 2)    /* Flush Tx FIFO */
+#define UDCCS0_DRWF        (1 << 16)    /* Device remote wakeup feature */
+#define UDCCS0_SST        (1 << 4)    /* Sent stall */
+#define UDCCS0_FST        (1 << 5)    /* Force stall */
+#define UDCCS0_RNE        (1 << 6)    /* Receive FIFO no empty */
+#define UDCCS0_SA        (1 << 7)    /* Setup active */
+
+/* Bulk IN - Endpoint 1,6,11 */
+#define UDCCS1            __REG(0x40600104)  /* UDC Endpoint 1 (IN) 
Control/Status Register */
+#define UDCCS6            __REG(0x40600028)  /* UDC Endpoint 6 (IN) 
Control/Status Register */
+#define UDCCS11            __REG(0x4060003C)  /* UDC Endpoint 11 (IN) 
Control/Status Register */
+
+#define UDCCS_BI_TFS        (1 << 0)    /* Transmit FIFO service */
+#define UDCCS_BI_TPC        (1 << 1)    /* Transmit packet complete */
+#define UDCCS_BI_FTF        (1 << 8)    /* Flush Tx FIFO */
+#define UDCCS_BI_TUR        (1 << 3)    /* Transmit FIFO underrun */
+#define UDCCS_BI_SST        (1 << 4)    /* Sent stall */
+#define UDCCS_BI_FST        (1 << 5)    /* Force stall */
+#define UDCCS_BI_TSP        (1 << 7)    /* Transmit short packet */
+
+/* Bulk OUT - Endpoint 2,7,12 */
+#define UDCCS2                __REG(0x40600108)  /* UDC Endpoint 2 
(OUT) Control/Status Register */
+#define UDCCS7                __REG(0x4060002C)  /* UDC Endpoint 7 
(OUT) Control/Status Register */
+#define UDCCS12                __REG(0x40600040)  /* UDC Endpoint 12 
(OUT) Control/Status Register */
+
+#define UDCCS_BO_RFS        (1 << 0)    /* Receive FIFO service */
+#define UDCCS_BO_RPC        (1 << 1)    /* Receive packet complete */
+#define UDCCS_BO_DME        (1 << 3)    /* DMA enable */
+#define UDCCS_BO_SST        (1 << 4)    /* Sent stall */
+#define UDCCS_BO_FST        (1 << 5)    /* Force stall */
+#define UDCCS_BO_RNE        (1 << 6)    /* Receive FIFO not empty */
+#define UDCCS_BO_RSP        (1 << 7)    /* Receive short packet */
+
+/* Isochronous IN - Endpoint 3,8,13 */
+#define UDCCS3        __REG(0x4060001C)  /* UDC Endpoint 3 (IN) 
Control/Status Register */
+#define UDCCS8        __REG(0x40600030)  /* UDC Endpoint 8 (IN) 
Control/Status Register */
+#define UDCCS13        __REG(0x40600044)  /* UDC Endpoint 13 (IN) 
Control/Status Register */
+
+#define UDCCS_II_TFS    (1 << 0)    /* Transmit FIFO service */
+#define UDCCS_II_TPC    (1 << 1)    /* Transmit packet complete */
+#define UDCCS_II_FTF    (1 << 2)    /* Flush Tx FIFO */
+#define UDCCS_II_TUR    (1 << 3)    /* Transmit FIFO underrun */
+#define UDCCS_II_TSP    (1 << 7)    /* Transmit short packet */
+
+/* Isochronous OUT - Endpoint 4,9,14 */
+#define UDCCS4        __REG(0x40600020)  /* UDC Endpoint 4 (OUT) 
Control/Status Register */
+#define UDCCS9        __REG(0x40600034)  /* UDC Endpoint 9 (OUT) 
Control/Status Register */
+#define UDCCS14        __REG(0x40600048)  /* UDC Endpoint 14 (OUT) 
Control/Status Register */
+
+#define UDCCS_IO_RFS    (1 << 0)    /* Receive FIFO service */
+#define UDCCS_IO_RPC    (1 << 1)    /* Receive packet complete */
+#define UDCCS_IO_ROF    (1 << 3)    /* Receive overflow */
+#define UDCCS_IO_DME    (1 << 3)    /* DMA enable */
+#define UDCCS_IO_RNE    (1 << 6)    /* Receive FIFO not empty */
+#define UDCCS_IO_RSP    (1 << 7)    /* Receive short packet */
+
+/* Interrupt IN - Endpoint 5,10,15 */
+#define UDCCS5        __REG(0x40600024)  /* UDC Endpoint 5 (Interrupt) 
Control/Status Register */
+#define UDCCS10        __REG(0x40600038)  /* UDC Endpoint 10 
(Interrupt) Control/Status Register */
+#define UDCCS15        __REG(0x4060004C)  /* UDC Endpoint 15 
(Interrupt) Control/Status Register */
+
+#define UDCCS_INT_TFS    (1 << 0)    /* Transmit FIFO service */
+#define UDCCS_INT_TPC    (1 << 1)    /* Transmit packet complete */
+#define UDCCS_INT_FTF    (1 << 2)    /* Flush Tx FIFO */
+#define UDCCS_INT_TUR    (1 << 3)    /* Transmit FIFO underrun */
+#define UDCCS_INT_SST    (1 << 4)    /* Sent stall */
+#define UDCCS_INT_FST    (1 << 5)    /* Force stall */
+#define UDCCS_INT_TSP    (1 << 7)    /* Transmit short packet */
+
+#define UFNRH        __REG(0x40600060)  /* UDC Frame Number Register 
High */
+#define UFNRL        __REG(0x40600014)  /* UDC Frame Number Register Low */
+#define UBCR2        __REG(0x40600208)  /* UDC Byte Count Reg 2 */
+#define UBCR4        __REG(0x4060006c)  /* UDC Byte Count Reg 4 */
+#define UBCR7        __REG(0x40600070)  /* UDC Byte Count Reg 7 */
+#define UBCR9        __REG(0x40600074)  /* UDC Byte Count Reg 9 */
+#define UBCR12        __REG(0x40600078)  /* UDC Byte Count Reg 12 */
+#define UBCR14        __REG(0x4060007c)  /* UDC Byte Count Reg 14 */
+#define UDDR0        __REG(0x40600300)  /* UDC Endpoint 0 Data Register */
+#define UDDR1        __REG(0x40600304)  /* UDC Endpoint 1 Data Register */
+#define UDDR2        __REG(0x40600308)  /* UDC Endpoint 2 Data Register */
+#define UDDR3        __REG(0x40600200)  /* UDC Endpoint 3 Data Register */
+#define UDDR4        __REG(0x40600400)  /* UDC Endpoint 4 Data Register */
+#define UDDR5        __REG(0x406000A0)  /* UDC Endpoint 5 Data Register */
+#define UDDR6        __REG(0x40600600)  /* UDC Endpoint 6 Data Register */
+#define UDDR7        __REG(0x40600680)  /* UDC Endpoint 7 Data Register */
+#define UDDR8        __REG(0x40600700)  /* UDC Endpoint 8 Data Register */
+#define UDDR9        __REG(0x40600900)  /* UDC Endpoint 9 Data Register */
+#define UDDR10        __REG(0x406000C0)  /* UDC Endpoint 10 Data 
Register */
+#define UDDR11        __REG(0x40600B00)  /* UDC Endpoint 11 Data 
Register */
+#define UDDR12        __REG(0x40600B80)  /* UDC Endpoint 12 Data 
Register */
+#define UDDR13        __REG(0x40600C00)  /* UDC Endpoint 13 Data 
Register */
+#define UDDR14        __REG(0x40600E00)  /* UDC Endpoint 14 Data 
Register */
+#define UDDR15        __REG(0x406000E0)  /* UDC Endpoint 15 Data 
Register */
+
+#define UICR0        __REG(0x40600004)  /* UDC Interrupt Control 
Register 0 */
+
+#define UICR0_IM0    (1 << 0)    /* Interrupt mask ep 0 */
+#define UICR0_IM1    (1 << 1)    /* Interrupt mask ep 1 */
+#define UICR0_IM2    (1 << 2)    /* Interrupt mask ep 2 */
+#define UICR0_IM3    (1 << 3)    /* Interrupt mask ep 3 */
+#define UICR0_IM4    (1 << 4)    /* Interrupt mask ep 4 */
+#define UICR0_IM5    (1 << 5)    /* Interrupt mask ep 5 */
+#define UICR0_IM6    (1 << 6)    /* Interrupt mask ep 6 */
+#define UICR0_IM7    (1 << 7)    /* Interrupt mask ep 7 */
+
+#define UICR1        __REG(0x40600008)  /* UDC Interrupt Control 
Register 1 */
+
+#define UICR1_IM8    (1 << 0)    /* Interrupt mask ep 8 */
+#define UICR1_IM9    (1 << 1)    /* Interrupt mask ep 9 */
+#define UICR1_IM10    (1 << 2)    /* Interrupt mask ep 10 */
+#define UICR1_IM11    (1 << 3)    /* Interrupt mask ep 11 */
+#define UICR1_IM12    (1 << 4)    /* Interrupt mask ep 12 */
+#define UICR1_IM13    (1 << 5)    /* Interrupt mask ep 13 */
+#define UICR1_IM14    (1 << 6)    /* Interrupt mask ep 14 */
+#define UICR1_IM15    (1 << 7)    /* Interrupt mask ep 15 */
+
+#define USIR0        __REG(0x4060000C)  /* UDC Status Interrupt 
Register 0 */
+
+#define USIR0_IR0    (1 << 0)    /* Interrup request ep 0 */
+#define USIR0_IR1    (1 << 2)    /* Interrup request ep 1 */
+#define USIR0_IR2    (1 << 4)    /* Interrup request ep 2 */
+#define USIR0_IR3    (1 << 3)    /* Interrup request ep 3 */
+#define USIR0_IR4    (1 << 4)    /* Interrup request ep 4 */
+#define USIR0_IR5    (1 << 5)    /* Interrup request ep 5 */
+#define USIR0_IR6    (1 << 6)    /* Interrup request ep 6 */
+#define USIR0_IR7    (1 << 7)    /* Interrup request ep 7 */
+
+#define USIR1        __REG(0x40600010)  /* UDC Status Interrupt 
Register 1 */
+
+#define USIR1_IR8    (1 << 0)    /* Interrup request ep 8 */
+#define USIR1_IR9    (1 << 1)    /* Interrup request ep 9 */
+#define USIR1_IR10    (1 << 2)    /* Interrup request ep 10 */
+#define USIR1_IR11    (1 << 3)    /* Interrup request ep 11 */
+#define USIR1_IR12    (1 << 4)    /* Interrup request ep 12 */
+#define USIR1_IR13    (1 << 5)    /* Interrup request ep 13 */
+#define USIR1_IR14    (1 << 6)    /* Interrup request ep 14 */
+#define USIR1_IR15    (1 << 7)    /* Interrup request ep 15 */
+
+#define UDCCR           __REG(0x40600000) /* UDC Control Register */
+#define UDCCR_OEN        (1 << 31)    /* On-the-Go Enable */
+#define UDCCR_AALTHNP    (1 << 30)    /* A-device Alternate Host 
Negotiation Protocol Port Support */
+#define UDCCR_AHNP        (1 << 29)    /* A-device Host Negotiation 
Protocol Support */
+#define UDCCR_BHNP        (1 << 28)    /* B-device Host Negotiation 
Protocol Enable */
+#define UDCCR_DWRE        (1 << 16)    /* Device Remote Wake-up Enable */
+#define UDCCR_ACN        (0x03 << 11)    /* Active UDC configuration 
Number */
+#define UDCCR_ACN_S        11
+#define UDCCR_AIN        (0x07 << 8)    /* Active UDC interface Number */
+#define UDCCR_AIN_S        8
+#define UDCCR_AAISN        (0x07 << 5)    /* Active UDC Alternate 
Interface  Setting Number */
+#define UDCCR_AAISN_S    5
+#define UDCCR_SMAC        (1 << 4)    /* Switch Endpoint Memory to 
Active Configuration */
+#define UDCCR_EMCE        (1 << 3)    /* Endpoint Memory Configuration 
Error */
+#define UDCCR_UDR        (1 << 2)    /* UDC Resume */
+#define UDCCR_UDA        (1 << 1)    /* UDC Active */
+#define UDCCR_UDE        (1 << 0)    /* UDC Enable */
+
+#define UDCICR0         __REG(0x40600004) /* UDC Interrupt Control 
Register0 */
+#define UDCICR1         __REG(0x40600008) /* UDC Interrupt Control 
Register1 */
+#define UDCICR_FIFOERR    (1 << 1)    /* FIFO Error interrupt for EP */
+#define UDCICR_PKTCOMPL (1 << 0)    /* Packet Complete interrupt for EP */
+
+#define UDC_INT_FIFOERROR  (0x2)
+#define UDC_INT_PACKETCMP  (0x1)
+
+#define UDCICR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCICR1_IECC    (1 << 31)    /* IntEn - Configuration Change */
+#define UDCICR1_IESOF    (1 << 30)    /* IntEn - Start of Frame */
+#define UDCICR1_IERU    (1 << 29)    /* IntEn - Resume */
+#define UDCICR1_IESU    (1 << 28)    /* IntEn - Suspend */
+#define UDCICR1_IERS    (1 << 27)    /* IntEn - Reset */
+
+#define UDCISR0         __REG(0x4060000C) /* UDC Interrupt Status 
Register 0 */
+#define UDCISR1         __REG(0x40600010) /* UDC Interrupt Status 
Register 1 */
+#define UDCISR_INT(n,intr) (((intr) & 0x03) << (((n) & 0x0F) * 2))
+#define UDCISR1_IRCC    (1 << 31)    /* IntEn - Configuration Change */
+#define UDCISR1_IRSOF    (1 << 30)    /* IntEn - Start of Frame */
+#define UDCISR1_IRRU    (1 << 29)    /* IntEn - Resume */
+#define UDCISR1_IRSU    (1 << 28)    /* IntEn - Suspend */
+#define UDCISR1_IRRS    (1 << 27)    /* IntEn - Reset */
+
+
+#define UDCFNR                 __REG(0x40600014) /* UDC Frame Number 
Register */
+#define UDCOTGICR            __REG(0x40600018) /* UDC On-The-Go 
interrupt control */
+#define UDCOTGICR_IESF        (1 << 24)    /* OTG SET_FEATURE command 
recvd */
+#define UDCOTGICR_IEXR        (1 << 17)    /* Extra Transciever 
Interrupt Rising Edge Interrupt Enable */
+#define UDCOTGICR_IEXF        (1 << 16)    /* Extra Transciever 
Interrupt Falling Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40R    (1 << 9)    /* OTG Vbus Valid 4.0V Rising 
Edge Interrupt Enable */
+#define UDCOTGICR_IEVV40F    (1 << 8)    /* OTG Vbus Valid 4.0V Falling 
Edge Interrupt Enable */
+#define UDCOTGICR_IEVV44R    (1 << 7)    /* OTG Vbus Valid 4.4V Rising 
Edge  Interrupt Enable */
+#define UDCOTGICR_IEVV44F    (1 << 6)    /* OTG Vbus Valid 4.4V Falling 
Edge Interrupt Enable */
+#define UDCOTGICR_IESVR        (1 << 5)    /* OTG Session Valid Rising 
Edge Interrupt Enable */
+#define UDCOTGICR_IESVF        (1 << 4)    /* OTG Session Valid Falling 
Edge Interrupt Enable */
+#define UDCOTGICR_IESDR        (1 << 3)    /* OTG A-Device SRP Detect 
Rising Edge Interrupt Enable */
+#define UDCOTGICR_IESDF        (1 << 2)    /* OTG A-Device SRP Detect 
Falling  Edge Interrupt Enable */
+#define UDCOTGICR_IEIDR        (1 << 1)    /* OTG ID Change Rising Edge 
Interrupt Enable */
+#define UDCOTGICR_IEIDF        (1 << 0)    /* OTG ID Change Falling 
Edge Interrupt Enable */
+
+#define UDCCSN(x)            __REG2(0x40600100, (x) << 2)
+#define UDCCSR0                __REG(0x40600100) /* UDC Control/Status 
register - Endpoint 0 */
+
+#define UDCCSR0_SA    (1 << 7)    /* Setup Active */
+#define UDCCSR0_RNE    (1 << 6)    /* Receive FIFO Not Empty */
+#define UDCCSR0_FST    (1 << 5)    /* Force Stall */
+#define UDCCSR0_SST    (1 << 4)    /* Sent Stall */
+#define UDCCSR0_DME    (1 << 3)    /* DMA Enable */
+#define UDCCSR0_FTF    (1 << 2)    /* Flush Transmit FIFO */
+#define UDCCSR0_IPR    (1 << 1)    /* IN Packet Ready */
+#define UDCCSR0_OPC    (1 << 0)    /* OUT Packet Complete */
+
+#define UDCCSRA         __REG(0x40600104) /* UDC Control/Status 
register - Endpoint A */
+#define UDCCSRB         __REG(0x40600108) /* UDC Control/Status 
register - Endpoint B */
+#define UDCCSRC         __REG(0x4060010C) /* UDC Control/Status 
register - Endpoint C */
+#define UDCCSRD         __REG(0x40600110) /* UDC Control/Status 
register - Endpoint D */
+#define UDCCSRE         __REG(0x40600114) /* UDC Control/Status 
register - Endpoint E */
+#define UDCCSRF         __REG(0x40600118) /* UDC Control/Status 
register - Endpoint F */
+#define UDCCSRG         __REG(0x4060011C) /* UDC Control/Status 
register - Endpoint G */
+#define UDCCSRH         __REG(0x40600120) /* UDC Control/Status 
register - Endpoint H */
+#define UDCCSRI         __REG(0x40600124) /* UDC Control/Status 
register - Endpoint I */
+#define UDCCSRJ         __REG(0x40600128) /* UDC Control/Status 
register - Endpoint J */
+#define UDCCSRK         __REG(0x4060012C) /* UDC Control/Status 
register - Endpoint K */
+#define UDCCSRL         __REG(0x40600130) /* UDC Control/Status 
register - Endpoint L */
+#define UDCCSRM         __REG(0x40600134) /* UDC Control/Status 
register - Endpoint M */
+#define UDCCSRN         __REG(0x40600138) /* UDC Control/Status 
register - Endpoint N */
+#define UDCCSRP         __REG(0x4060013C) /* UDC Control/Status 
register - Endpoint P */
+#define UDCCSRQ         __REG(0x40600140) /* UDC Control/Status 
register - Endpoint Q */
+#define UDCCSRR         __REG(0x40600144) /* UDC Control/Status 
register - Endpoint R */
+#define UDCCSRS         __REG(0x40600148) /* UDC Control/Status 
register - Endpoint S */
+#define UDCCSRT         __REG(0x4060014C) /* UDC Control/Status 
register - Endpoint T */
+#define UDCCSRU         __REG(0x40600150) /* UDC Control/Status 
register - Endpoint U */
+#define UDCCSRV         __REG(0x40600154) /* UDC Control/Status 
register - Endpoint V */
+#define UDCCSRW         __REG(0x40600158) /* UDC Control/Status 
register - Endpoint W */
+#define UDCCSRX         __REG(0x4060015C) /* UDC Control/Status 
register - Endpoint X */
+
+#define UDCCSR_DPE    (1 << 9)    /* Data Packet Error */
+#define UDCCSR_FEF    (1 << 8)    /* Flush Endpoint FIFO */
+#define UDCCSR_SP    (1 << 7)    /* Short Packet Control/Status */
+#define UDCCSR_BNE    (1 << 6)    /* Buffer Not Empty (IN endpoints) */
+#define UDCCSR_BNF    (1 << 6)    /* Buffer Not Full (OUT endpoints) */
+#define UDCCSR_FST    (1 << 5)    /* Force STALL */
+#define UDCCSR_SST    (1 << 4)    /* Sent STALL */
+#define UDCCSR_DME    (1 << 3)    /* DMA Enable */
+#define UDCCSR_TRN    (1 << 2)    /* Tx/Rx NAK */
+#define UDCCSR_PC    (1 << 1)    /* Packet Complete */
+#define UDCCSR_FS    (1 << 0)    /* FIFO needs service */
+
+#define UDCBCN(x)    __REG2(0x40600200, (x)<<2)
+#define UDCBCR0         __REG(0x40600200) /* Byte Count Register - EP0 */
+#define UDCBCRA         __REG(0x40600204) /* Byte Count Register - EPA */
+#define UDCBCRB         __REG(0x40600208) /* Byte Count Register - EPB */
+#define UDCBCRC         __REG(0x4060020C) /* Byte Count Register - EPC */
+#define UDCBCRD         __REG(0x40600210) /* Byte Count Register - EPD */
+#define UDCBCRE         __REG(0x40600214) /* Byte Count Register - EPE */
+#define UDCBCRF         __REG(0x40600218) /* Byte Count Register - EPF */
+#define UDCBCRG         __REG(0x4060021C) /* Byte Count Register - EPG */
+#define UDCBCRH         __REG(0x40600220) /* Byte Count Register - EPH */
+#define UDCBCRI         __REG(0x40600224) /* Byte Count Register - EPI */
+#define UDCBCRJ         __REG(0x40600228) /* Byte Count Register - EPJ */
+#define UDCBCRK         __REG(0x4060022C) /* Byte Count Register - EPK */
+#define UDCBCRL         __REG(0x40600230) /* Byte Count Register - EPL */
+#define UDCBCRM         __REG(0x40600234) /* Byte Count Register - EPM */
+#define UDCBCRN         __REG(0x40600238) /* Byte Count Register - EPN */
+#define UDCBCRP         __REG(0x4060023C) /* Byte Count Register - EPP */
+#define UDCBCRQ         __REG(0x40600240) /* Byte Count Register - EPQ */
+#define UDCBCRR         __REG(0x40600244) /* Byte Count Register - EPR */
+#define UDCBCRS         __REG(0x40600248) /* Byte Count Register - EPS */
+#define UDCBCRT         __REG(0x4060024C) /* Byte Count Register - EPT */
+#define UDCBCRU         __REG(0x40600250) /* Byte Count Register - EPU */
+#define UDCBCRV         __REG(0x40600254) /* Byte Count Register - EPV */
+#define UDCBCRW         __REG(0x40600258) /* Byte Count Register - EPW */
+#define UDCBCRX         __REG(0x4060025C) /* Byte Count Register - EPX */
+
+#define UDCDN(x)    __REG2(0x40600300, (x)<<2)
+#define PHYS_UDCDN(x)    (0x40600300 + ((x)<<2))
+#define PUDCDN(x)    (volatile u32 *)(io_p2v(PHYS_UDCDN((x))))
+#define UDCDR0          __REG(0x40600300) /* Data Register - EP0 */
+#define UDCDRA          __REG(0x40600304) /* Data Register - EPA */
+#define UDCDRB          __REG(0x40600308) /* Data Register - EPB */
+#define UDCDRC          __REG(0x4060030C) /* Data Register - EPC */
+#define UDCDRD          __REG(0x40600310) /* Data Register - EPD */
+#define UDCDRE          __REG(0x40600314) /* Data Register - EPE */
+#define UDCDRF          __REG(0x40600318) /* Data Register - EPF */
+#define UDCDRG          __REG(0x4060031C) /* Data Register - EPG */
+#define UDCDRH          __REG(0x40600320) /* Data Register - EPH */
+#define UDCDRI          __REG(0x40600324) /* Data Register - EPI */
+#define UDCDRJ          __REG(0x40600328) /* Data Register - EPJ */
+#define UDCDRK          __REG(0x4060032C) /* Data Register - EPK */
+#define UDCDRL          __REG(0x40600330) /* Data Register - EPL */
+#define UDCDRM          __REG(0x40600334) /* Data Register - EPM */
+#define UDCDRN          __REG(0x40600338) /* Data Register - EPN */
+#define UDCDRP          __REG(0x4060033C) /* Data Register - EPP */
+#define UDCDRQ          __REG(0x40600340) /* Data Register - EPQ */
+#define UDCDRR          __REG(0x40600344) /* Data Register - EPR */
+#define UDCDRS          __REG(0x40600348) /* Data Register - EPS */
+#define UDCDRT          __REG(0x4060034C) /* Data Register - EPT */
+#define UDCDRU          __REG(0x40600350) /* Data Register - EPU */
+#define UDCDRV          __REG(0x40600354) /* Data Register - EPV */
+#define UDCDRW          __REG(0x40600358) /* Data Register - EPW */
+#define UDCDRX          __REG(0x4060035C) /* Data Register - EPX */
+
+#define UDCCN(x)       __REG2(0x40600400, (x)<<2)
+#define UDCCRA          __REG(0x40600404) /* Configuration register EPA */
+#define UDCCRB          __REG(0x40600408) /* Configuration register EPB */
+#define UDCCRC          __REG(0x4060040C) /* Configuration register EPC */
+#define UDCCRD          __REG(0x40600410) /* Configuration register EPD */
+#define UDCCRE          __REG(0x40600414) /* Configuration register EPE */
+#define UDCCRF          __REG(0x40600418) /* Configuration register EPF */
+#define UDCCRG          __REG(0x4060041C) /* Configuration register EPG */
+#define UDCCRH          __REG(0x40600420) /* Configuration register EPH */
+#define UDCCRI          __REG(0x40600424) /* Configuration register EPI */
+#define UDCCRJ          __REG(0x40600428) /* Configuration register EPJ */
+#define UDCCRK          __REG(0x4060042C) /* Configuration register EPK */
+#define UDCCRL          __REG(0x40600430) /* Configuration register EPL */
+#define UDCCRM          __REG(0x40600434) /* Configuration register EPM */
+#define UDCCRN          __REG(0x40600438) /* Configuration register EPN */
+#define UDCCRP          __REG(0x4060043C) /* Configuration register EPP */
+#define UDCCRQ          __REG(0x40600440) /* Configuration register EPQ */
+#define UDCCRR          __REG(0x40600444) /* Configuration register EPR */
+#define UDCCRS          __REG(0x40600448) /* Configuration register EPS */
+#define UDCCRT          __REG(0x4060044C) /* Configuration register EPT */
+#define UDCCRU          __REG(0x40600450) /* Configuration register EPU */
+#define UDCCRV          __REG(0x40600454) /* Configuration register EPV */
+#define UDCCRW          __REG(0x40600458) /* Configuration register EPW */
+#define UDCCRX          __REG(0x4060045C) /* Configuration register EPX */
+
+#define UDCCONR_CN        (0x03 << 25)    /* Configuration Number */
+#define UDCCONR_CN_S    (25)
+#define UDCCONR_IN        (0x07 << 22)    /* Interface Number */
+#define UDCCONR_IN_S    (22)
+#define UDCCONR_AISN    (0x07 << 19)    /* Alternate Interface Number */
+#define UDCCONR_AISN_S    (19)
+#define UDCCONR_EN        (0x0f << 15)    /* Endpoint Number */
+#define UDCCONR_EN_S    (15)
+#define UDCCONR_ET        (0x03 << 13)    /* Endpoint Type: */
+#define UDCCONR_ET_S    (13)
+#define UDCCONR_ET_INT    (0x03 << 13)    /*   Interrupt */
+#define UDCCONR_ET_BULK    (0x02 << 13)    /*   Bulk */
+#define UDCCONR_ET_ISO    (0x01 << 13)    /*   Isochronous */
+#define UDCCONR_ET_NU    (0x00 << 13)    /*   Not used */
+#define UDCCONR_ED        (1 << 12)    /* Endpoint Direction */
+#define UDCCONR_MPS        (0x3ff << 2)    /* Maximum Packet Size */
+#define UDCCONR_MPS_S    (2)
+#define UDCCONR_DE        (1 << 1)    /* Double Buffering Enable */
+#define UDCCONR_EE        (1 << 0)    /* Endpoint Enable */
+
+
+#define UDC_INT_FIFOERROR  (0x2)
+#define UDC_INT_PACKETCMP  (0x1)
+
+#define UDC_FNR_MASK     (0x7ff)
+
+#define UDCCSR_WR_MASK  (UDCCSR_DME|UDCCSR_FST)
+#define UDC_BCR_MASK    (0x3ff)
+
+#endif /* __PXA27X_UDC_REGS_H */
diff --git a/drivers/usb/usbdcore_pxa27x.c b/drivers/usb/usbdcore_pxa27x.c
new file mode 100644
index 0000000..db8708e
--- /dev/null
+++ b/drivers/usb/usbdcore_pxa27x.c
@@ -0,0 +1,714 @@
+/*
+ * PXA27x USB device driver for u-boot.
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2008 Vivek Kutal     <vivek.kutal@azingo.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 <config.h>
+#include <asm/byteorder.h>
+#include <usbdcore.h>
+#include <usbdcore_ep0.h>
+#include <asm/arch/hardware.h>
+#include <usbdcore_pxa2xx.h>
+#include "pxa27x_udc_regs.h"
+
+#define UDC_MAX_ENDPOINTS    24    /* number of endpoints on this UDC */
+
+
+static struct urb *ep0_urb = NULL;
+static struct usb_device_instance *udc_device;
+static int ep0state = EP0_IDLE;
+
+#ifdef USBDDBG
+static void udc_dump_buffer(char *name, u8 *buf, int len)
+{
+    int i, p, flag = 1;
+
+    usbdbg("%s - buf %p, len %d", name, buf, len);
+    for (i = p = 0; i < len; i++, p++) {
+        if (p == 0) {
+            flag = 0;
+            usbdbg("\t");
+        }
+
+        usbdbg("%02x ", buf[i]);
+
+        if (p == 15) {
+            flag = 1;
+            usbdbg("\n");
+            p = -1;
+        }
+    }
+    if (!flag)
+        usbdbg("\n");
+}
+#else
+#define udc_dump_buffer(name, buf, len)        /* void */
+#endif
+
+static inline void udc_ack_int_UDCCR(int mask)
+{
+    USIR1    = mask | USIR1;
+}
+
+/*
+ * If the endpoint has an active tx_urb, then the next packet of data 
from the
+ * URB is written to the tx FIFO.
+ * The total amount of data in the urb is given by urb->actual_length.
+ * The maximum amount of data that can be sent in any one packet is 
given by
+ * endpoint->tx_packetSize.
+ * The number of data bytes from this URB that have already been 
transmitted
+ * is given by endpoint->sent.
+ * endpoint->last is updated by this routine with the number of data bytes
+ * transmitted in this packet.
+ */
+static int udc_write_urb(struct usb_endpoint_instance *endpoint)
+{
+    struct urb *urb = endpoint->tx_urb;
+    int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+
+    u32 *addr32 = (u32 *) &UDCDN(ep_num),
+        *data32 = (u32 *) urb->buffer;
+    u8  *addr8 = (u8 *) &UDCDN(ep_num),
+        *data8 = (u8 *) urb->buffer;
+    unsigned int i, n, w, b, is_short;
+    int timeout = 2000;    /* 2ms */
+
+    if (!urb || !urb->actual_length)
+        return -1;
+
+    n = MIN(urb->actual_length - endpoint->sent, endpoint->tx_packetSize);
+    if (n <= 0)
+        return -1;
+
+    usbdbg("write urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+    usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+        urb->buffer, urb->buffer_length, urb->actual_length);
+    usbdbg("endpoint: sent %d, tx_packetSize %d, last %d",
+        endpoint->sent, endpoint->tx_packetSize, endpoint->last);
+#endif
+
+    is_short = n != endpoint->tx_packetSize;
+    w = n / 4;
+    b = n % 4;
+    usbdbg("n %d%s w %d b %d", n, is_short ? "-s" : "", w, b);
+    udc_dump_buffer("urb write", data8 + endpoint->sent, n);
+    /* Prepare for data send */
+
+    if (ep_num)
+        UDCCSN(ep_num) = UDCCSR_PC;
+
+    for (i = 0; i < w; i++)
+        *addr32 = data32[endpoint->sent/4 + i];
+    for (i = 0; i < b; i++)
+        *addr8 = data8[endpoint->sent + w*4 + i];
+
+    /* Set "Packet Complete" if less data then tx_packetSize */
+    if (is_short)
+        UDCCSN(ep_num) = ep_num ? UDCCSR_SP : UDCCSR0_IPR;
+
+    /* Wait for data sent */
+    while (!(UDCCSN(ep_num) & (ep_num ? UDCCSR_PC : UDCCSR0_IPR))) {
+        if (ep_num) {
+            if (timeout-- == 0)
+                return -1;
+            else
+                udelay(1);
+        };
+    }
+    endpoint->last = n;
+
+    if(ep_num) {
+        usbd_tx_complete(endpoint);
+    } else {
+        endpoint->sent += n;
+        endpoint->last -= n;
+    }
+
+    if( (endpoint->tx_urb->actual_length - endpoint->sent) <= 0 ) {
+        urb->actual_length = 0;
+        endpoint->sent = 0;
+        endpoint->last = 0;
+    }
+
+    if ((endpoint->sent >= urb->actual_length) && (!ep_num)) {
+        usbdbg("ep0 IN stage done");
+        if(is_short)
+            ep0state = EP0_IDLE;
+        else
+            ep0state = EP0_XFER_COMPLETE;
+    }
+
+    return 0;
+}
+
+static int udc_read_urb(struct usb_endpoint_instance *endpoint)
+{
+    struct urb *urb = endpoint->rcv_urb;
+    int ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+    u32 *addr32 = (u32 *) &UDCDN(ep_num),
+        *data32 = (u32 *) urb->buffer;
+    unsigned int i, n, is_short ;
+
+    usbdbg("read urb on ep %d", ep_num);
+#if defined(USBDDBG) && defined(USBDPARANOIA)
+    usbdbg("urb: buf %p, buf_len %d, actual_len %d",
+        urb->buffer, urb->buffer_length, urb->actual_length);
+    usbdbg("endpoint: rcv_packetSize %d",
+        endpoint->rcv_packetSize);
+#endif
+
+    if (UDCCSN(ep_num) & UDCCSR_BNE)
+        n = UDCBCN(ep_num) & 0x3ff;
+    else /* zlp */
+        n = 0;
+    is_short = n != endpoint->rcv_packetSize;
+
+    usbdbg("n %d%s", n, is_short ? "-s" : "");
+    for (i = 0; i < n; i += 4)
+        data32[urb->actual_length/4 + i/4] = *addr32;
+
+    udc_dump_buffer("urb read", (u8 *) data32, urb->actual_length + n);
+
+    usbd_rcv_complete(endpoint, n, 0);
+
+    return 0;
+}
+
+static int udc_read_urb_ep0(void)
+{
+    u32 *addr32 = (u32 *) &UDCDN(0),
+        *data32 = (u32 *) ep0_urb->buffer;
+    u8  *addr8 = (u8 *) &UDCDN(0),
+        *data8 = (u8 *) ep0_urb->buffer;
+    unsigned int i, n, w, b;
+
+    n = UDCBCR0;
+    w = n / 4;
+    b = n % 4;
+
+    for (i = 0; i < w; i++) {
+        data32[ep0_urb->actual_length/4 + i] = *addr32;
+        ep0_urb->actual_length += 4;
+    }
+
+    for (i = 0; i < b; i++ ) {
+        data8[ep0_urb->actual_length + w*4 + i] = *addr8;
+        ep0_urb->actual_length++;
+    }
+
+    UDCCSR0 = UDCCSR0_OPC | UDCCSR0_IPR;
+    if(ep0_urb->actual_length == ep0_urb->device_request.wLength)
+        return 1;
+    return 0;
+}
+
+static void udc_handle_ep0(struct usb_endpoint_instance *endpoint)
+{
+    u32 udccsr0 = UDCCSR0;
+    u32 *data = (u32 *) &ep0_urb->device_request;
+    int i;
+
+    usbdbg("udccsr0 %x", udccsr0);
+
+    /* Clear stall status */
+    if (udccsr0 & UDCCSR0_SST) {
+        usberr("clear stall status");
+        UDCCSR0 = UDCCSR0_SST;
+        ep0state = EP0_IDLE;
+    }
+
+    /* previous request unfinished?  non-error iff back-to-back ... */
+    if ((udccsr0 & UDCCSR0_SA) != 0 && ep0state != EP0_IDLE)
+        ep0state = EP0_IDLE;
+
+    switch (ep0state) {
+        case EP0_IDLE :
+
+            udccsr0 = UDCCSR0;
+            /* Start control request? */
+            if ((udccsr0 & (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE))
+                == (UDCCSR0_OPC | UDCCSR0_SA | UDCCSR0_RNE)) {
+
+                /* Read SETUP packet.
+                 * SETUP packet size is 8 bytes (aka 2 words)
+                 */
+                usbdbg("try reading SETUP packet");
+                for (i = 0; i < 2; i++) {
+                if ((UDCCSR0 & UDCCSR0_RNE) == 0) {
+                    usberr("setup packet too short (%d)", i);
+                    goto stall;
+                }
+                data[i] = UDCDR0;
+            }
+            UDCCSR0 |= (UDCCSR0_OPC | UDCCSR0_SA);
+            if ((UDCCSR0 & UDCCSR0_RNE) != 0) {
+                usberr("setup packet too long");
+                goto stall;
+            }
+
+            udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+
+            if(ep0_urb->device_request.wLength == 0) {
+
+                usbdbg("Zero Data control Packet\n");
+
+                if(ep0_recv_setup(ep0_urb)) {
+                    usberr("Invalid Setup Packet\n");
+                    udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+                    goto stall;
+                }
+                UDCCSR0 = UDCCSR0_IPR;
+                ep0state = EP0_IDLE;
+            }
+            else {
+                /* Check direction */
+                if ((ep0_urb->device_request.bmRequestType
+                    & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
+                    ep0state = EP0_OUT_DATA;
+                    ep0_urb->buffer = (u8 *)ep0_urb->buffer_data;
+                    ep0_urb->buffer_length = sizeof(ep0_urb->buffer_data);
+                    ep0_urb->actual_length = 0;
+                    UDCCSR0 = UDCCSR0_IPR;
+                }
+                else {
+                    /* The ep0_recv_setup function has already placed our
+                     * response packet data in ep0_urb->buffer and the
+                     * packet length in ep0_urb->actual_length.
+                     */
+                    if (ep0_recv_setup(ep0_urb)) {
+stall:
+                        usberr("Invalid setup packet");
+                        udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+                        ep0state= EP0_IDLE;
+                        UDCCSR0 = UDCCSR0_SA|UDCCSR0_OPC | UDCCSR0_FST 
| UDCCS0_FTF;
+                        return;
+                    }
+
+                    endpoint->tx_urb = ep0_urb;
+                    endpoint->sent = 0;
+                    usbdbg("EP0_IN_DATA");
+                    ep0state = EP0_IN_DATA;
+                    if(udc_write_urb(endpoint) < 0)
+                        goto stall;
+
+                }
+            }
+            return;
+        }
+        else if ((udccsr0 & (UDCCSR0_OPC |UDCCSR0_SA))
+            == (UDCCSR0_OPC|UDCCSR0_SA)) {
+            usberr("Setup Active but no data. Stalling ....\n");
+            goto stall;
+        }
+        else {
+            usbdbg("random early IRQs");
+            /* Some random early IRQs:
+             * - we acked FST
+             * - IPR cleared
+             * - OPC got set, without SA (likely status stage)
+             */
+            UDCCSR0 = udccsr0 & (UDCCSR0_SA | UDCCSR0_OPC);
+
+        }
+        break;
+
+        case EP0_OUT_DATA :
+
+            if ((udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_SA)) {
+                if(udc_read_urb_ep0()) {
+read_complete:
+                    ep0state = EP0_IDLE;
+                    if (ep0_recv_setup(ep0_urb)) {
+                        /* Not a setup packet, stall next EP0 
transaction */
+                        udc_dump_buffer("ep0 setup read", (u8 *) data, 8);
+                        usberr("can't parse setup packet\n");
+                        goto stall;
+                    }
+                }
+            }
+            else if(!(udccsr0 & UDCCSR0_OPC) && !(udccsr0 & UDCCSR0_IPR)) {
+                if(ep0_urb->device_request.wLength == 
ep0_urb->actual_length)
+                    goto read_complete;
+                usberr("Premature Status\n");
+                ep0state = EP0_IDLE;
+            }
+            break;
+
+        case EP0_IN_DATA :
+            /* GET_DESCRIPTOR etc */
+            if (udccsr0 & UDCCSR0_OPC) {
+                UDCCSR0 = UDCCSR0_OPC | UDCCSR0_FTF;
+                usberr("ep0in premature status");
+                ep0state = EP0_IDLE;
+            }
+            else {
+                /* irq was IPR clearing */
+                if(udc_write_urb(endpoint) < 0) {
+                    usberr("ep0_write_error\n");
+                    goto stall;
+                }
+            }
+            break;
+
+        case EP0_XFER_COMPLETE:
+            UDCCSR0 = UDCCSR0_IPR;
+            ep0state = EP0_IDLE;
+            break;
+
+        default:
+            usbdbg("Default\n");
+    }
+    USIR0 = USIR0_IR0;
+}
+
+static void udc_handle_ep(struct usb_endpoint_instance *endpoint)
+{
+    int ep_addr = endpoint->endpoint_address;
+    int ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+    int ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+
+    u32 flags = UDCCSN(ep_num) & (UDCCSR_SST | UDCCSR_TRN);
+    if (flags)
+        UDCCSN(ep_num) = flags;
+
+    if (ep_isout)
+        udc_read_urb(endpoint);
+    else
+        udc_write_urb(endpoint);
+
+    UDCCSN(ep_num) = UDCCSR_PC;
+}
+
+static void udc_state_changed(void)
+{
+    int config, interface, alternate;
+
+    UDCCR |= UDCCR_SMAC;
+
+    config = (UDCCR & UDCCR_ACN) >> UDCCR_ACN_S;
+    interface =  (UDCCR & UDCCR_AIN) >> UDCCR_AIN_S;
+    alternate = (UDCCR & UDCCR_AAISN) >> UDCCR_AAISN_S;
+
+    usbdbg("New UDC settings are: conf %d - inter %d - alter %d",
+        config, interface, alternate);
+
+    usbd_device_event_irq (udc_device, DEVICE_CONFIGURED, 0);
+
+    UDCISR1 = UDCISR1_IRCC;
+}
+
+
+
+void udc_irq(void)
+{
+    int            handled;
+    struct usb_endpoint_instance *endpoint;
+    int ep_num, i;
+    u32 udcisr0;
+
+    do {
+        handled = 0;
+        /* Suspend Interrupt Request */
+        if (USIR1 & UDCCR_SUSIR) {
+
+            usbdbg("Suspend\n");
+            udc_ack_int_UDCCR(UDCCR_SUSIR);
+            handled = 1;
+            ep0state = EP0_IDLE;
+        }
+
+        /* Resume Interrupt Request */
+        if (USIR1 & UDCCR_RESIR) {
+            udc_ack_int_UDCCR(UDCCR_RESIR);
+            handled = 1;
+            usbdbg( "USB resume\n");
+
+        }
+
+        if (USIR1 & (1<<31) ){
+            handled=1;
+            udc_state_changed();
+        }
+
+        /* Reset Interrupt Request */
+        if (USIR1 & UDCCR_RSTIR) {
+            udc_ack_int_UDCCR(UDCCR_RSTIR);
+            handled = 1;
+            usbdbg("Reset\n");
+            usbd_device_event_irq(udc_device, DEVICE_RESET, 0);
+        } else {
+            if(USIR0)
+                usbdbg("UISR0: %x \n",USIR0);
+
+            if (USIR0 & 0x2)    USIR0 = 0x2;
+
+            /* Control traffic */
+            if (USIR0  & USIR0_IR0) {
+                handled = 1;
+                udc_handle_ep0(udc_device->bus->endpoint_array);
+                USIR0 = USIR0_IR0;
+            }
+
+            endpoint = udc_device->bus->endpoint_array;
+            for (i = 0; i < udc_device->bus->max_endpoints; i++) {
+                ep_num = (endpoint[i].endpoint_address) & 
USB_ENDPOINT_NUMBER_MASK;
+                if (!ep_num)
+                    continue;
+                udcisr0 = UDCISR0;
+                if (udcisr0 & UDCISR_INT(ep_num, UDC_INT_PACKETCMP)) {
+                    UDCISR0 = UDCISR_INT(ep_num, UDC_INT_PACKETCMP);
+                    udc_handle_ep(&endpoint[i]);
+
+                }
+            }
+
+        }
+
+    } while (handled);
+}
+
+/* The UDCCR reg contains mask and interrupt status bits,
+ * so using '|=' isn't safe as it may ack an interrupt.
+ */
+#define UDCCR_OEN   (1 << 31)   /* On-the-Go Enable */
+#define UDCCR_MASK_BITS     (UDCCR_OEN | UDCCR_UDE)
+
+static inline void udc_set_mask_UDCCR(int mask)
+{
+    UDCCR = (UDCCR & UDCCR_MASK_BITS) | (mask & UDCCR_MASK_BITS);
+}
+
+static inline void udc_clear_mask_UDCCR(int mask)
+{
+    UDCCR = (UDCCR & UDCCR_MASK_BITS) & ~(mask & UDCCR_MASK_BITS);
+}
+
+
+static void pio_irq_enable(int ep_num)
+{
+    if (ep_num < 16)
+        UDCICR0 |= 3 << (ep_num * 2);
+    else {
+        ep_num -= 16;
+        UDCICR1 |= 3 << (ep_num * 2);
+    }
+}
+
+/*
+ * udc_set_nak
+ *
+ * Allow upper layers to signal lower layers should not accept more RX data
+ */
+void udc_set_nak(int ep_num)
+{
+    /* TODO */
+}
+
+/*
+ * udc_unset_nak
+ *
+ * Suspend sending of NAK tokens for DATA OUT tokens on a given endpoint.
+ * Switch off NAKing on this endpoint to accept more data output from host.
+ */
+void udc_unset_nak(int ep_num)
+{
+    /* TODO */
+}
+
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint)
+{
+    return udc_write_urb(endpoint);
+}
+
+/* Associate a physical endpoint with endpoint instance */
+void udc_setup_ep(struct usb_device_instance *device, unsigned int id, 
struct usb_endpoint_instance *endpoint)
+{
+    int ep_num, ep_addr, ep_isout, ep_type, ep_size;
+    int config, interface, alternate;
+    u32 tmp;
+
+    usbdbg("setting up endpoint id %d", id);
+
+    if (!endpoint) {
+        usberr("endpoint void!");
+        return;
+    }
+
+    ep_num = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK;
+    if (ep_num >= UDC_MAX_ENDPOINTS) {
+        usberr("unable to setup ep %d!",ep_num);
+        return;
+    }
+
+    pio_irq_enable(ep_num);
+    if (ep_num == 0) {
+        /* Done for ep0 */
+        return;
+    }
+
+    config = 1;
+    interface = 0;
+    alternate = 0;
+
+    usbdbg("config %d - interface %d - alternate %d",
+        config, interface, alternate);
+
+    ep_addr = endpoint->endpoint_address;
+    ep_num = ep_addr & USB_ENDPOINT_NUMBER_MASK;
+    ep_isout = (ep_addr & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT;
+    ep_type = ep_isout ? endpoint->rcv_attributes : 
endpoint->tx_attributes;
+    ep_size = ep_isout ? endpoint->rcv_packetSize : 
endpoint->tx_packetSize;
+
+    usbdbg("addr %x, num %d, dir %s, type %s, packet size %d",
+        ep_addr, ep_num,
+        ep_isout ? "out" : "in",
+        ep_type == USB_ENDPOINT_XFER_ISOC ? "isoc" :
+           ep_type == USB_ENDPOINT_XFER_BULK ? "bulk" :
+           ep_type == USB_ENDPOINT_XFER_INT ? "int" : "???",
+        ep_size
+        );
+
+    /* Configure UDCCRx */
+    tmp = 0;
+    tmp |= (config << UDCCONR_CN_S) & UDCCONR_CN;
+    tmp |= (interface << UDCCONR_IN_S) & UDCCONR_IN;
+    tmp |= (alternate << UDCCONR_AISN_S) & UDCCONR_AISN;
+    tmp |= (ep_num << UDCCONR_EN_S) & UDCCONR_EN;
+    tmp |= (ep_type << UDCCONR_ET_S) & UDCCONR_ET;
+    tmp |= ep_isout ? 0 : UDCCONR_ED;
+    tmp |= (ep_size << UDCCONR_MPS_S ) & UDCCONR_MPS;
+    tmp |= /* UDCCONR_DE | */ UDCCONR_EE;
+
+    UDCCN(ep_num) = tmp;
+
+    usbdbg("UDCCR%c = %x", 'A' + ep_num-1, UDCCN(ep_num));
+    usbdbg("UDCCSR%c = %x", 'A' + ep_num-1, UDCCSN(ep_num));
+}
+
+
+
+#define CONFIG_USB_DEV_PULLUP_GPIO 87
+
+/* Connect the USB device to the bus */
+void udc_connect(void)
+{
+    usbdbg("UDC connect");
+
+    /* Turn on the USB connection by enabling the pullup resistor */
+    set_GPIO_mode(CONFIG_USB_DEV_PULLUP_GPIO | GPIO_OUT);
+    GPSR(CONFIG_USB_DEV_PULLUP_GPIO) = 
GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Disconnect the USB device to the bus */
+void udc_disconnect(void)
+{
+    usbdbg("UDC disconnect");
+
+    /* Turn off the USB connection by disabling the pullup resistor */
+    GPCR(CONFIG_USB_DEV_PULLUP_GPIO) = 
GPIO_bit(CONFIG_USB_DEV_PULLUP_GPIO);
+}
+
+/* Switch on the UDC */
+void udc_enable(struct usb_device_instance *device)
+{
+
+    ep0state = EP0_IDLE;
+    CKEN |= CKEN11_USB;
+
+    /* enable endpoint 0, A, B's Packet Complete Interrupt. */
+    UDCICR0 = 0x0000003f;
+    UDCICR1 = 0xa8000000;
+
+    /* clear the interrupt status/control registers */
+    UDCISR0 = 0xffffffff;
+    UDCISR1 = 0xffffffff;
+
+    /* set UDC-enable */
+    udc_set_mask_UDCCR( UDCCR_UDE);
+
+    udc_device = device;
+    if (!ep0_urb)
+        ep0_urb = 
usbd_alloc_urb(udc_device,udc_device->bus->endpoint_array);
+    else
+        usbinfo("ep0_urb %p already allocated", ep0_urb);
+
+    usbdbg("UDC Enabled\n");
+}
+
+/* Need to check this again */
+void udc_disable(void)
+{
+    usbdbg("disable UDC");
+
+    udc_clear_mask_UDCCR(UDCCR_UDE);
+
+    /* Disable clock for USB device */
+    CKEN &= ~CKEN11_USB;
+
+    /* Free ep0 URB */
+    if (ep0_urb) {
+        usbd_dealloc_urb(ep0_urb);
+        ep0_urb = NULL;
+    }
+
+    /* Reset device pointer */
+    udc_device = NULL;
+}
+
+/* Allow udc code to do any additional startup */
+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);
+
+    /* Some USB controller driver implementations signal
+     * DEVICE_HUB_CONFIGURED and DEVICE_RESET events here.
+     * DEVICE_HUB_CONFIGURED causes a transition to the state 
STATE_POWERED,
+     * and DEVICE_RESET causes a transition to the state STATE_DEFAULT.
+     */
+    udc_enable(device);
+}
+
+/* Initialize h/w stuff */
+int udc_init(void)
+{
+    udc_device = NULL;
+    usbdbg("PXA27x usbd start");
+
+    /* Disable the UDC */
+    udc_clear_mask_UDCCR(UDCCR_UDE);
+
+    /* Disable clock for USB device */
+    CKEN &= ~CKEN11_USB;
+
+    /* Disable IRQs: we don't use them */
+    UDCICR0 = UDCICR1 = 0;
+
+    return 0;
+}
diff --git a/include/usbdcore_pxa2xx.h b/include/usbdcore_pxa2xx.h
new file mode 100644
index 0000000..3d04f18
--- /dev/null
+++ b/include/usbdcore_pxa2xx.h
@@ -0,0 +1,68 @@
+/*
+ * PXA27x register declarations and HCD data structures
+ *
+ * Copyright (C) 2007 Rodolfo Giometti <giometti@linux.it>
+ * Copyright (C) 2007 Eurotech S.p.A. <info@eurotech.it>
+ *
+ * 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 __USBDCORE_PXA270X_H__
+#define __USBDCORE_PXA270X_H__
+
+#include <asm/byteorder.h>
+
+/* Endpoint 0 states */
+#define EP0_IDLE            0
+#define EP0_IN_DATA            1
+#define EP0_OUT_DATA        2
+#define EP0_XFER_COMPLETE   3
+
+
+/* Endpoint parameters */
+#define MAX_ENDPOINTS        4
+#define EP_MAX_PACKET_SIZE    64
+
+#define EP0_MAX_PACKET_SIZE     16
+#define UDC_OUT_ENDPOINT        0x02
+#define UDC_OUT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_IN_ENDPOINT         0x03
+#define UDC_IN_PACKET_SIZE      EP_MAX_PACKET_SIZE
+#define UDC_INT_ENDPOINT        0x01
+#define UDC_INT_PACKET_SIZE     EP_MAX_PACKET_SIZE
+#define UDC_BULK_PACKET_SIZE    EP_MAX_PACKET_SIZE
+
+void udc_irq (void);
+/* Flow control */
+void udc_set_nak(int epid);
+void udc_unset_nak (int epid);
+
+/* Higher level functions for abstracting away from specific device */
+int udc_endpoint_write(struct usb_endpoint_instance *endpoint);
+
+int  udc_init (void);
+
+void udc_enable(struct usb_device_instance *device);
+void udc_disable(void);
+
+void udc_connect(void);
+void udc_disconnect(void);
+
+void udc_startup_events(struct usb_device_instance *device);
+void udc_setup_ep(struct usb_device_instance *device, unsigned int ep, 
struct usb_endpoint_instance *endpoint);
+
+#endif
-- 
1.5.6.3

             reply	other threads:[~2009-02-20 12:36 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-20 12:36 Vivek Kutal [this message]
2009-02-20 16:15 ` [U-Boot] [RFC] PXA27X UDC Support Jean-Christophe PLAGNIOL-VILLARD
2009-02-21 11:37 ` Rodolfo Giometti
2009-02-21 15:48   ` Vivek Kutal

Reply instructions:

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

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

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

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

  git send-email \
    --in-reply-to=499EA3BD.9010908@azingo.com \
    --to=vivek.kutal@azingo.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

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

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.