]> rtime.felk.cvut.cz Git - zynq/linux.git/commitdiff
usb: gadget: Updated to support little endian systems.
authorSubbaraya Sundeep Bhatta <subbaraya.sundeep.bhatta@xilinx.com>
Wed, 3 Apr 2013 14:56:18 +0000 (20:26 +0530)
committerMichal Simek <michal.simek@xilinx.com>
Wed, 3 Apr 2013 15:26:49 +0000 (17:26 +0200)
Updated to support little endian systems.
Cleaned up the code for setup packet handling.

Signed-off-by: Subbaraya Sundeep Bhatta <sbhatta@xilinx.com>
drivers/usb/gadget/xilinx_udc.c

index 79b47f3703d90bcca1db3ba9751ecc70626b7ead..6d1984675d4cb9400e0d45044a42f85a5312ddf3 100644 (file)
@@ -221,39 +221,7 @@ struct xusb_request {
  * as unions so that the parameters can be used in the request processing.
  */
 static struct {
-       union {
-               u8 StandardDeviceRequest;
-               u8 bmRequestType;
-       } byte0;
-       union {
-               u8 FbRequest;
-               u8 bRequest;
-       } byte1;
-       union {
-               struct {
-                       u8 bDescriptorType;
-                       u8 bDescriptorIndex;
-               } byte23;
-               u16 FwValue;
-               u16 wValue;
-               u16 wFeatureSelector;
-       } word1;
-       union {
-               struct {
-                       u8 byteh;
-                       u8 bytel;
-               } byte45;
-               u16 wTargetSelector;
-               u16 FwIndex;
-               u16 wIndex;
-       } word2;
-       union {
-               struct {
-                       u8 byteh;
-                       u8 bytel;
-               } byte67;
-               u16 wLength;
-       } word3;
+       struct usb_ctrlrequest setup;
        u8 *contreadptr;
        u8 *contwriteptr;
        u32 contreadcount;
@@ -263,18 +231,6 @@ static struct {
        u8 contreaddatabuffer[64];
 } ch9_cmdbuf;
 
-
- /* union for 32 bit integer memory access to the Dual Port RAM.*/
-static union {
-       u32 word;
-       struct {
-               u8 zero;
-               u8 one;
-               u8 two;
-               u8 three;
-       } byte;
-} usbmemdata;
-
 /*
  * Initial Fixed locations provided for endpoint memory address
  * in the USB core. The user needs to modify this as per his application.
@@ -303,6 +259,16 @@ static inline struct xusb_udc *to_udc(struct usb_gadget *g)
        return container_of(g, struct xusb_udc, gadget);
 }
 
+static void xusb_write32(u32 val, void __iomem *addr)
+{
+       iowrite32(val, addr);
+}
+
+static unsigned int xusb_read32(void __iomem *addr)
+{
+       return ioread32(addr);
+}
+
 static void xusb_write32_be(u32 val, void __iomem *addr)
 {
        iowrite32be(val, addr);
@@ -1617,7 +1583,7 @@ static void set_configuration(struct xusb_udc *udc)
 {
        u32 epcfgreg;
 
-       switch (ch9_cmdbuf.word1.wValue) {
+       switch (ch9_cmdbuf.setup.wValue) {
        case 0:
                /*
                 * This configuration value resets the device to the
@@ -1659,9 +1625,9 @@ static void set_clear_feature(struct xusb_udc *udc, int flag)
        u8 outinbit;
        u32 epcfgreg;
 
-       switch (ch9_cmdbuf.byte0.bmRequestType) {
+       switch (ch9_cmdbuf.setup.bRequestType) {
        case STANDARD_OUT_DEVICE:
-               switch (ch9_cmdbuf.word1.wValue) {
+               switch (ch9_cmdbuf.setup.wValue) {
                case USB_DEVICE_REMOTE_WAKEUP:
                        /* User needs to add code here.*/
                        break;
@@ -1684,9 +1650,9 @@ static void set_clear_feature(struct xusb_udc *udc, int flag)
                break;
 
        case STANDARD_OUT_ENDPOINT:
-               if (!ch9_cmdbuf.word1.wValue) {
-                       endpoint = ch9_cmdbuf.word2.wIndex & 0xf;
-                       outinbit = ch9_cmdbuf.word2.wIndex & 0x80;
+               if (!ch9_cmdbuf.setup.wValue) {
+                       endpoint = ch9_cmdbuf.setup.wIndex & 0xf;
+                       outinbit = ch9_cmdbuf.setup.wIndex & 0x80;
                        outinbit = outinbit >> 7;
 
                        /* Make sure direction matches.*/
@@ -1764,10 +1730,10 @@ static void set_clear_feature(struct xusb_udc *udc, int flag)
 static int execute_command(struct xusb_udc *udc)
 {
 
-       if ((ch9_cmdbuf.byte0.bmRequestType & USB_TYPE_MASK) ==
+       if ((ch9_cmdbuf.setup.bRequestType & USB_TYPE_MASK) ==
            USB_TYPE_STANDARD) {
                /* Process the chapter 9 command.*/
-               switch (ch9_cmdbuf.byte1.bRequest) {
+               switch (ch9_cmdbuf.setup.bRequest) {
 
                case USB_REQ_CLEAR_FEATURE:
                        set_clear_feature(udc, 0);
@@ -1783,21 +1749,20 @@ static int execute_command(struct xusb_udc *udc)
 
                case USB_REQ_SET_CONFIGURATION:
                        set_configuration(udc);
-                       return ch9_cmdbuf.byte1.bRequest;
+                       return ch9_cmdbuf.setup.bRequest;
 
                default:
                        /*
                         * Return the same request to application for
                         * handling.
                         */
-                       return ch9_cmdbuf.byte1.bRequest;
+                       return ch9_cmdbuf.setup.bRequest;
                }
 
        } else
-               if ((ch9_cmdbuf.byte0.bmRequestType & USB_TYPE_MASK) ==
+               if ((ch9_cmdbuf.setup.bRequestType & USB_TYPE_MASK) ==
                                        USB_TYPE_CLASS)
-                       return ch9_cmdbuf.byte1.bRequest;
-
+                       return ch9_cmdbuf.setup.bRequest;
        return 0;
 }
 
@@ -1817,36 +1782,22 @@ static int process_setup_pkt(struct xusb_udc *udc, struct usb_ctrlrequest *ctrl)
        /* Load up the chapter 9 command buffer.*/
        ep0rambase = (u32 __force *) (udc->base_address +
                                  XUSB_SETUP_PKT_ADDR_OFFSET);
+       memcpy((void *)&ch9_cmdbuf.setup, (void *)ep0rambase, 8);
 
-       /* Get the first 4 bytes of the setup packet */
-       usbmemdata.word = *ep0rambase;
-       ch9_cmdbuf.byte0.bmRequestType = usbmemdata.byte.zero;
-       ch9_cmdbuf.byte1.bRequest = usbmemdata.byte.one;
-       ch9_cmdbuf.word1.byte23.bDescriptorIndex = usbmemdata.byte.two;
-       ch9_cmdbuf.word1.byte23.bDescriptorType = usbmemdata.byte.three;
-
-       /* Get the last 4 bytes of the setup packet.*/
-       ep0rambase += 1;
-       usbmemdata.word = *ep0rambase;
+       ctrl->bRequestType = ch9_cmdbuf.setup.bRequestType;
+       ctrl->bRequest     = ch9_cmdbuf.setup.bRequest;
+       ctrl->wValue       = ch9_cmdbuf.setup.wValue;
+       ctrl->wIndex       = ch9_cmdbuf.setup.wIndex;
+       ctrl->wLength      = ch9_cmdbuf.setup.wLength;
 
-       /*
-        * Byte swapping for next 4 bytes for BE machines is defined in
-        * the different layout of BECB verses LECB.
-        */
-       ch9_cmdbuf.word2.byte45.bytel = usbmemdata.byte.zero;
-       ch9_cmdbuf.word2.byte45.byteh = usbmemdata.byte.one;
-       ch9_cmdbuf.word3.byte67.bytel = usbmemdata.byte.two;
-       ch9_cmdbuf.word3.byte67.byteh = usbmemdata.byte.three;
-       ctrl->bRequestType = ch9_cmdbuf.byte0.bmRequestType;
-       ctrl->bRequest = ch9_cmdbuf.byte1.bRequest;
-       ctrl->wValue = cpu_to_le16(ch9_cmdbuf.word1.wValue);
-       ctrl->wIndex = cpu_to_le16(ch9_cmdbuf.word2.wIndex);
-       ctrl->wLength = cpu_to_le16(ch9_cmdbuf.word3.wLength);
+       ch9_cmdbuf.setup.wValue = cpu_to_le16(ch9_cmdbuf.setup.wValue);
+       ch9_cmdbuf.setup.wIndex = cpu_to_le16(ch9_cmdbuf.setup.wIndex);
+       ch9_cmdbuf.setup.wLength = cpu_to_le16(ch9_cmdbuf.setup.wLength);
 
        /* Restore ReadPtr to data buffer.*/
        ch9_cmdbuf.contreadptr = &ch9_cmdbuf.contreaddatabuffer[0];
 
-       if (ch9_cmdbuf.byte0.bmRequestType & USB_DIR_IN) {
+       if (ch9_cmdbuf.setup.bRequestType & USB_DIR_IN) {
                /* Execute the get command.*/
                ch9_cmdbuf.setupseqrx = STATUS_PHASE;
                ch9_cmdbuf.setupseqtx = DATA_PHASE;
@@ -1855,7 +1806,7 @@ static int process_setup_pkt(struct xusb_udc *udc, struct usb_ctrlrequest *ctrl)
                /* Execute the put command.*/
                ch9_cmdbuf.setupseqrx = DATA_PHASE;
                ch9_cmdbuf.setupseqtx = STATUS_PHASE;
-               if (!ch9_cmdbuf.word3.wLength)
+               if (!ch9_cmdbuf.setup.wLength)
                        return execute_command(udc);
        }
        /* Control should never come here.*/
@@ -1901,7 +1852,7 @@ static void ep0_out_token(struct xusb_udc *udc)
                                                 XUSB_EP_BUF0COUNT_OFFSET));
                udc->write_fn(1, (udc->base_address + XUSB_BUFFREADY_OFFSET));
 
-               if (ch9_cmdbuf.word3.wLength == ch9_cmdbuf.contreadcount)
+               if (ch9_cmdbuf.setup.wLength == ch9_cmdbuf.contreadcount)
                        execute_command(udc);
                break;
 
@@ -1924,16 +1875,16 @@ static void ep0_in_token(struct xusb_udc *udc)
 
        switch (ch9_cmdbuf.setupseqtx) {
        case STATUS_PHASE:
-               if (ch9_cmdbuf.byte1.bRequest == USB_REQ_SET_ADDRESS) {
+               if (ch9_cmdbuf.setup.bRequest == USB_REQ_SET_ADDRESS) {
                        /* Set the address of the device.*/
-                       udc->write_fn(ch9_cmdbuf.word1.byte23.bDescriptorIndex,
+                       udc->write_fn(ch9_cmdbuf.setup.wValue,
                                        (udc->base_address +
                                        XUSB_ADDRESS_OFFSET));
                } else
-                       if (ch9_cmdbuf.byte1.bRequest == USB_REQ_SET_FEATURE) {
-                               if (ch9_cmdbuf.byte0.bmRequestType ==
+                       if (ch9_cmdbuf.setup.bRequest == USB_REQ_SET_FEATURE) {
+                               if (ch9_cmdbuf.setup.bRequestType ==
                                        STANDARD_OUT_DEVICE) {
-                                       if (ch9_cmdbuf.word1.wValue ==
+                                       if (ch9_cmdbuf.setup.wValue ==
                                                USB_DEVICE_TEST_MODE)
                                                udc->write_fn(TEST_J,
                                                        (udc->base_address +
@@ -2266,6 +2217,14 @@ static int xudc_init(struct device *dev, struct resource *regs_res,
 
        spin_lock_init(&udc->lock);
 
+       /* Check for IP endianness */
+       udc->write_fn(TEST_J, (udc->base_address + XUSB_TESTMODE_OFFSET));
+       if ((udc->read_fn(udc->base_address + XUSB_TESTMODE_OFFSET))
+                       != TEST_J) {
+               controller.write_fn = xusb_write32;
+               controller.read_fn = xusb_read32;
+       }
+       udc->write_fn(0, (udc->base_address + XUSB_TESTMODE_OFFSET));
        xudc_reinit(udc);
 
        /* Set device address to 0.*/