12cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang/*
22cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * Copyright (c) 2014-2015, Linaro Ltd and Contributors. All rights reserved.
32cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * Copyright (c) 2014-2015, Hisilicon Ltd and Contributors. All rights reserved.
42cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang *
52cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * Redistribution and use in source and binary forms, with or without
62cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * modification, are permitted provided that the following conditions are met:
72cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang *
82cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * Redistributions of source code must retain the above copyright notice, this
92cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * list of conditions and the following disclaimer.
102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang *
112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * Redistributions in binary form must reproduce the above copyright notice,
122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * this list of conditions and the following disclaimer in the documentation
132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * and/or other materials provided with the distribution.
142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang *
152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * Neither the name of ARM nor the names of its contributors may be used
162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * to endorse or promote products derived from this software without specific
172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * prior written permission.
182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang *
192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang * POSSIBILITY OF SUCH DAMAGE.
302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang */
312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <assert.h>
332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <ctype.h>
342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <debug.h>
3559fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang#include <gpio.h>
362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <hi6220.h>
372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <mmio.h>
382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <partitions.h>
392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <platform_def.h>
402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <sp804_timer.h>
412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <string.h>
422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include <usb.h>
432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#include "hikey_private.h"
44a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj#include <bl_common.h>
452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define NUM_ENDPOINTS			16
472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define USB_BLOCK_HIGH_SPEED_SIZE	512
492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
50554b28ac1d6a6c75893fb5831107fee464ce581dVishal Bhoj#define VERSION_BOOTLOADER	"0.4"
51554b28ac1d6a6c75893fb5831107fee464ce581dVishal Bhoj
522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstruct ep_type {
532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned char		active;
542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned char		busy;
552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned char		done;
562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int		rc;
572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int		size;
582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang};
592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstruct usb_endpoint {
612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_endpoint	*next;
622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int		maxpkt;
632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_request	*req;
642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned char		num;
652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned char		in;
662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang};
672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstruct usb_config_bundle {
692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_config_descriptor config;
702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_interface_descriptor interface;
712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_endpoint_descriptor ep1;
722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_endpoint_descriptor ep2;
732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang} __attribute__ ((packed));
742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic setup_packet ctrl_req[NUM_ENDPOINTS]
762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned char ctrl_resp[2]
782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct ep_type endpoints[NUM_ENDPOINTS]
812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangdwc_otg_dev_dma_desc_t dma_desc
842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangdwc_otg_dev_dma_desc_t dma_desc_ep0
862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangdwc_otg_dev_dma_desc_t dma_desc_in
882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangdwc_otg_dev_dma_desc_t dma_desc_addr
902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct usb_config_bundle config_bundle
932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct usb_device_descriptor device_descriptor
952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct usb_request rx_req
982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct usb_request tx_req
1002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
1012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
102b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuangstatic struct usb_string_descriptor serial_string
103b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang__attribute__ ((section("tzfw_coherent_mem")));
104b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang
1052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic const struct usb_string_descriptor string_devicename = {
1062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	24,
1072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	USB_DT_STRING,
1082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	{'A', 'n', 'd', 'r', 'o', 'i', 'd', ' ', '2', '.', '0'}
1092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang};
1102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic const struct usb_string_descriptor serial_string_descriptor = {
1122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	34,
1132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	USB_DT_STRING,
1142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	{'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}
1152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang};
1162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic const struct usb_string_descriptor lang_descriptor = {
1182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	4,
1192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	USB_DT_STRING,
1202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	{0x0409}	/* en-US */
1212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang};
1222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usb_rx_cmd_complete(unsigned actual, int stat);
1242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usb_rx_data_complete(unsigned actual, int status);
1252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned int rx_desc_bytes = 0;
1272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned long rx_addr;
1282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned long rx_length;
1292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned int last_one = 0;
1302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic char *cmdbuf;
1312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct usb_endpoint ep1in, ep1out;
1322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic int g_usb_enum_flag = 0;
1332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangint usb_need_reset = 0;
1352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic int usb_drv_port_speed(void)
1372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
1382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* 2'b00 High speed (PHY clock is at 30MHz or 60MHz) */
1392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return (mmio_read_32(DSTS) & 2) == 0 ? 1 : 0;
1402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
1412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void reset_endpoints(void)
1432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
1442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int i;
1452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
1462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	INFO("enter reset_endpoints.\n");
1482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	for (i = 0; i < NUM_ENDPOINTS; i++) {
1492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		endpoints[i].active = 0;
1502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		endpoints[i].busy = 0;
1512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		endpoints[i].rc = -1;
1522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		endpoints[i].done = 1;
1532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
1542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EP0 IN ACTIVE NEXT=1 */
1562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPCTL0, 0x8800);
1572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EP0 OUT ACTIVE */
1592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPCTL0, 0x8000);
1602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Clear any pending OTG Interrupts */
1622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GOTGINT, ~0);
1632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Clear any pending interrupts */
1652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GINTSTS, ~0);
1662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPINT0, ~0);
1672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPINT0, ~0);
1682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPINT1, ~0);
1692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPINT1, ~0);
1702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* IN EP interrupt mask */
1722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPMSK, 0x0D);
1732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* OUT EP interrupt mask */
1742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPMSK, 0x0D);
1752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Enable interrupts on Ep0 */
1762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DAINTMSK, 0x00010001);
1772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
1782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/
1792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = DOEPTSIZ0_SUPCNT(3) | DOEPTSIZ0_PKTCNT |
1802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		(64 << DOEPTSIZ0_XFERSIZE_SHIFT);
1812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPTSIZ0, data);
1822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	//notes that:the compulsive conversion is expectable.
1832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.bs = 0x3;
1842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.mtrf = 0;
1852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.sr = 0;
1862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.l = 1;
1872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.ioc = 1;
1882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.sp = 0;
1892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.bytes = 64;
1902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.buf = (unsigned long)&ctrl_req;
1912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.sts = 0;
1922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_ep0.status.b.bs = 0x0;
1932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPDMA0, ((unsigned long)&(dma_desc_ep0)));
1942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("%s, &ctrl_req:%llx:%x, &dms_desc_ep0:%llx:%x\n",
1952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		__func__, (unsigned long)&ctrl_req, (unsigned long)&ctrl_req,
1962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		(unsigned long)&dma_desc_ep0, (unsigned long)&dma_desc_ep0);
1972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EP0 OUT ENABLE CLEARNAK */
1982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DOEPCTL0);
1992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPCTL0, (data | 0x84000000));
2002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("exit reset_endpoints. \n");
2022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
2032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic int usb_drv_request_endpoint(int type, int dir)
2052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
2062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int ep = 1;    /*FIXME*/
2072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int newbits, data;
2082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	newbits = (type << 18) | 0x10000000;
2102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
2122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * (type << 18):Endpoint Type (EPType)
2132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * 0x10000000:Endpoint Enable (EPEna)
2142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control.
2152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * (ep<<22):TxFIFO Number (TxFNum)
2162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint.
2172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
2182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (dir) {  // IN: to host
2192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DIEPCTL(ep));
2202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data &= ~0x000c0000;
2212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data |= newbits | (ep << 22) | 0x20000;
2222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPCTL(ep), data);
2232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {    // OUT: to device
2242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DOEPCTL(ep));
2252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data &= ~0x000c0000;
2262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data |= newbits;
2272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DOEPCTL(ep), data);
2282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
2292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].active = 1;	// true
2302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang    return ep | dir;
2322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
2332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_drv_release_endpoint(int ep)
2352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
2362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep = ep % NUM_ENDPOINTS;
2372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (ep < 1 || ep > NUM_ENDPOINTS)
2382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
2392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].active = 0;
2412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
2422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_config(void)
2442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
2452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
2462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	INFO("enter usb_config\n");
2482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GDFIFOCFG, DATA_FIFO_CONFIG);
2502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GRXFSIZ, RX_SIZE);
2512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GNPTXFSIZ, ENDPOINT_TX_SIZE);
2522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1);
2542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2);
2552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3);
2562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4);
2572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5);
2582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6);
2592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7);
2602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8);
2612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9);
2622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10);
2632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11);
2642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12);
2652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13);
2662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14);
2672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15);
2682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*Init global csr register.*/
2702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
2722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * set Periodic TxFIFO Empty Level,
2732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * Non-Periodic TxFIFO Empty Level,
2742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * Enable DMA, Unmask Global Intr
2752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
2762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	INFO("USB: DMA mode.\n");
2772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GAHBCFG, GAHBCFG_CTRL_MASK);
2782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*select 8bit UTMI+, ULPI Inerface*/
2802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	INFO("USB ULPI PHY\n");
2812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GUSBCFG, 0x2400);
2822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Detect usb work mode,host or device? */
2842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	do {
2852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(GINTSTS);
2862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} while (data & GINTSTS_CURMODE_HOST);
2872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("Enter device mode\n");
2882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	udelay(3);
2892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*Init global and device mode csr register.*/
2912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*set Non-Zero-Length status out handshake */
2922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK;
2932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DCFG, data);
2942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
2952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Interrupt unmask: IN event, OUT event, bus reset */
2962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE |
2972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	       GINTSTS_USBRST | GINTSTS_USBSUSP | GINTSTS_ERLYSUSP |
2982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	       GINTSTS_GOUTNAKEFF;
2992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GINTMSK, data);
3002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	do {
3022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(GINTSTS) & GINTSTS_ENUMDONE;
3032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} while (data);
3042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("USB Enum Done.\n");
3052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Clear any pending OTG Interrupts */
3072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GOTGINT, ~0);
3082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Clear any pending interrupts */
3092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GINTSTS, ~0);
3102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GINTMSK, ~0);
3112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(GOTGINT);
3122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data &= ~0x3000;
3132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GOTGINT, data);
3142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*endpoint settings cfg*/
3152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	reset_endpoints();
3162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	udelay(1);
3182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*init finish. and ready to transfer data*/
3202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Soft Disconnect */
3222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DCTL, 0x802);
3232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	udelay(10000);
3242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* Soft Reconnect */
3262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DCTL, 0x800);
3272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("exit usb_config.\n");
3282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
3292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_drv_set_address(int address)
3312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
3322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int cfg;
3332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cfg = mmio_read_32(DCFG);
3352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cfg &= ~0x7F0;
3362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cfg |= address << 4;
3372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DCFG, cfg);	// 0x7F0: device address
3382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
3392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void ep_send(int ep, const void *ptr, int len)
3412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
3422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
3432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].busy = 1;		// true
3452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].size = len;
3462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EPx OUT ACTIVE */
3482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DIEPCTL(ep)) | DXEPCTL_USBACTEP;
3492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPCTL(ep), data);
3502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* set DMA Address */
3522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!len) {
3532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* send one empty packet */
3542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.buf = 0;
3552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
3562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.buf = (unsigned long)ptr;
3572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
3582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.bs = 0x3;
3592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.l = 1;
3602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.ioc = 1;
3612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.sp = 1;
3622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.sts = 0;
3632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.bs = 0x0;
3642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dma_desc_in.status.b.bytes = len;
3652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPDMA(ep), (unsigned long)&dma_desc_in);
3662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DIEPCTL(ep));
3682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data |= DXEPCTL_EPENA | DXEPCTL_CNAK | DXEPCTL_NEXTEP(ep + 1);
3692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPCTL(ep), data);
3702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
3712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_drv_stall(int endpoint, char stall, char in)
3732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
3742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
3752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
3772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * STALL Handshake (Stall)
3782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
3792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DIEPCTL(endpoint));
3812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (in) {
3822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (stall)
3832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DIEPCTL(endpoint), data | 0x00200000);
3842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		else
3852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DIEPCTL(endpoint), data & ~0x00200000);
3862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
3872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (stall)
3882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPCTL(endpoint), data | 0x00200000);
3892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		else
3902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPCTL(endpoint), data & ~0x00200000);
3912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
3922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
3932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
3942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangint usb_drv_send_nonblocking(int endpoint, const void *ptr, int len)
3952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
3962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("%s, endpoint = %d, ptr = 0x%x, Len=%d.\n",
3972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		__func__, endpoint, ptr, len);
3982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep_send(endpoint % NUM_ENDPOINTS, ptr, len);
3992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return 0;
4002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
4012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_drv_cancel_all_transfers(void)
4032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
4042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	reset_endpoints();
4052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
4062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangint hiusb_epx_tx(unsigned ep, void *buf, unsigned len)
4082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
4092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int blocksize,packets;
4102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int epints;
4112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int cycle = 0;
4122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
4132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].busy = 1;		//true
4152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].size = len;
4162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	while (mmio_read_32(GINTSTS) & 0x40) {
4182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DCTL);
4192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data |= 0x100;
4202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DCTL, data);
4212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
4222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DIEPCTL(ep));
4242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data |= 0x08000000;
4252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPCTL(ep), data);
4262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EPx OUT ACTIVE */
4282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPCTL(ep), data | 0x8000);
4292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!ep) {
4302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		blocksize = 64;
4312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
4322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		blocksize = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
4332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
4342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	packets = (len + blocksize - 1) / blocksize;
4352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!len) {
4372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* one empty packet */
4382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPTSIZ(ep), 1 << 19);
4392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* NULL */
4402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.bs = 0x3;
4412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.l = 1;
4422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.ioc = 1;
4432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.sp = last_one;
4442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.bytes = 0;
4452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.buf = 0;
4462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.sts = 0;
4472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.bs = 0x0;
4482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPDMA(ep), (unsigned long)&dma_desc_in);
4492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
4502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPTSIZ(ep), len | (packets << 19));
4512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.bs = 0x3;
4522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.l = 1;
4532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.ioc = 1;
4542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.sp = last_one;
4552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.bytes = len;
4562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.buf = (unsigned long)buf;
4572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.sts = 0;
4582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc_in.status.b.bs = 0x0;
4592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPDMA(ep), (unsigned long)&dma_desc_in);
4602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
4612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cycle = 0;
4632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	while(1){
4642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DIEPINT(ep));
4652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if ((data & 0x2000) || (cycle > 10000)) {
4662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (cycle > 10000) {
4672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				NOTICE("Phase 2:ep(%d) status, DIEPCTL(%d) is [0x%x],"
4682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				       "DTXFSTS(%d) is [0x%x], DIEPINT(%d) is [0x%x],"
4692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				       "DIEPTSIZ(%d) is [0x%x] GINTSTS is [0x%x]\n",
4702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					ep, ep, data,
4712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					ep, mmio_read_32(DTXFSTS(ep)),
4722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					ep, mmio_read_32(DIEPINT(ep)),
4732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					ep, mmio_read_32(DIEPTSIZ(ep)),
4742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					mmio_read_32(GINTSTS));
4752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
4762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
4772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
4782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		cycle++;
4802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		udelay(10);
4812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
4822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("ep(%d) enable, DIEPCTL(%d) is [0x%x], DTXFSTS(%d) is [0x%x],"
4832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		"DIEPINT(%d) is [0x%x], DIEPTSIZ(%d) is [0x%x] \n",
4842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ep, ep, mmio_read_32(DIEPCTL(ep)),
4852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ep, mmio_read_32(DTXFSTS(ep)),
4862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ep, mmio_read_32(DIEPINT(ep)),
4872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ep, mmio_read_32(DIEPTSIZ(ep)));
4882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	__asm__ volatile("dsb	sy\n"
4902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 "isb	sy\n");
4912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DIEPCTL(ep));
4922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data |= 0x84000000;
4932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* epena & cnak*/
4942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DIEPCTL(ep), data);
4952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	__asm__ volatile("dsb	sy\n"
4962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 "isb	sy\n");
4972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
4982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cycle = 0;
4992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	while (1) {
5002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		epints = mmio_read_32(DIEPINT(ep)) & 1;
5012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if ((mmio_read_32(GINTSTS) & 0x40000) && epints) {
5022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("Tx succ:ep(%d), DTXFSTS(%d) is [0x%x] \n",
5032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				ep, ep, mmio_read_32(DTXFSTS(ep)));
5042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DIEPINT(ep), epints);
5052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (endpoints[ep].busy) {
5062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[ep].busy = 0;//false
5072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[ep].rc = 0;
5082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[ep].done = 1;//true
5092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
5102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
5112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
5122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		cycle++;
5132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		udelay(10);
5142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("loop for intr: ep(%d), DIEPCTL(%d) is [0x%x], ",
5152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			"DTXFSTS(%d) is [0x%x], DIEPINT(%d) is [0x%x] \n",
5162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			ep, ep, mmio_read_32(DIEPCTL(ep)),
5172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			ep, mmio_read_32(DTXFSTS(ep)),
5182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			ep, mmio_read_32(DIEPINT(ep)));
5192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (cycle > 1000000) {
5212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			WARN("Wait IOC intr over 10s! USB will reset\n");
5222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			usb_need_reset = 1;
5232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			return 1;
5242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
5252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
5262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cycle = 0;
5282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	while (1) {
5292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if ((mmio_read_32(DIEPINT(ep)) & 0x2000) || (cycle > 100000)) {
5302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (cycle > 100000){
5312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				WARN("all wait cycle is [%d]\n",cycle);
5322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
5332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
5342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
5352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		cycle++;
5372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		udelay(10);
5382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
5392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return 0;
5412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
5422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangint hiusb_epx_rx(unsigned ep, void *buf, unsigned len)
5442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
5452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int blocksize = 0, data;
5462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int packets;
5472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("ep%d rx, len = 0x%x, buf = 0x%x.\n", ep, len, buf);
5492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	endpoints[ep].busy = 1;//true
5512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EPx UNSTALL */
5522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DOEPCTL(ep)) & ~0x00200000;
5532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPCTL(ep), data);
5542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EPx OUT ACTIVE */
5552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DOEPCTL(ep)) | 0x8000;
5562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPCTL(ep), data);
5572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	blocksize = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
5592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	packets = (len + blocksize - 1) / blocksize;
5602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define MAX_RX_PACKET 0x3FF
5622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*Max recv packets is 1023*/
5642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (packets > MAX_RX_PACKET) {
5652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		endpoints[ep].size = MAX_RX_PACKET * blocksize;
5662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		len = MAX_RX_PACKET * blocksize;
5672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
5682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		endpoints[ep].size = len;
5692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
5702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!len) {
5722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* one empty packet */
5732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DOEPTSIZ(ep), 1 << 19);
5742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//NULL  /* dummy address */
5752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.bs = 0x3;
5762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.mtrf = 0;
5772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.sr = 0;
5782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.l = 1;
5792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.ioc = 1;
5802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.sp = 0;
5812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.bytes = 0;
5822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.buf = 0;
5832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.sts = 0;
5842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.bs = 0x0;
5852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
5862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DOEPDMA(ep), (unsigned long)&dma_desc);
5872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
5882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (len >= blocksize * 64) {
5892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			rx_desc_bytes = blocksize*64;
5902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		} else {
5912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			rx_desc_bytes = len;
5922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
5932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("rx len %d, rx_desc_bytes %d \n",len,rx_desc_bytes);
5942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.bs = 0x3;
5952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.mtrf = 0;
5962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.sr = 0;
5972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.l = 1;
5982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.ioc = 1;
5992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.sp = 0;
6002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.bytes = rx_desc_bytes;
6012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.buf = (unsigned long)buf;
6022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.sts = 0;
6032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		dma_desc.status.b.bs = 0x0;
6042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DOEPDMA(ep), (unsigned long)&dma_desc);
6062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
6072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* EPx OUT ENABLE CLEARNAK */
6082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(DOEPCTL(ep));
6092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data |= 0x84000000;
6102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(DOEPCTL(ep), data);
6112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return 0;
6122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangint usb_queue_req(struct usb_endpoint *ept, struct usb_request *req)
6152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (ept->in)
6172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		hiusb_epx_tx(ept->num, req->buf, req->length);
6182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	else
6192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		hiusb_epx_rx(ept->num, req->buf, req->length);
6202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return 0;
6222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void rx_cmd(void)
6252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_request *req = &rx_req;
6272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->buf = cmdbuf;
6282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->length = RX_REQ_LEN;
6292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->complete = usb_rx_cmd_complete;
6302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	usb_queue_req(&ep1out, req);
6312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void rx_data(void)
6342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_request *req = &rx_req;
6362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->buf = (void *)((unsigned long) rx_addr);
6382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->length = rx_length;
6392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->complete = usb_rx_data_complete;
6402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	usb_queue_req(&ep1out, req);
6412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid tx_status(const char *status)
6442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_request *req = &tx_req;
6462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int len = strlen(status);
6472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	memcpy(req->buf, status, (unsigned int)len);
6492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->length = (unsigned int)len;
6502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->complete = 0;
6512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	usb_queue_req(&ep1in, req);
6522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid fastboot_tx_status(const char *status)
6552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	tx_status(status);
6572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	rx_cmd();
6582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid tx_dump_page(const char *ptr, int len)
6612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_request *req = &tx_req;
6632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	memcpy(req->buf, ptr, (unsigned int)len);
6652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->length = (unsigned int)len;
6662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	req->complete = 0;
6672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	usb_queue_req(&ep1in, req);
6682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usb_rx_data_complete(unsigned actual, int status)
6722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if(status != 0)
6752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
6762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if(actual > rx_length) {
6782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		actual = rx_length;
6792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
6802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	rx_addr += actual;
6822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	rx_length -= actual;
6832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if(rx_length > 0) {
6852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_data();
6862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
6872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		tx_status("OKAY");
6882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_cmd();
6892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
6902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
6922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usb_status(unsigned online, unsigned highspeed)
6932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
6942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (online) {
6952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		INFO("usb: online (%s)\n", highspeed ? "highspeed" : "fullspeed");
6962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_cmd();
6972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
6982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
6992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_handle_control_request(setup_packet* req)
7012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
7022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	const void* addr = NULL;
7032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int size = -1;
704b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang	int i;
7052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int maxpacket;
7062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
707b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang	char *serialno;
7082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_endpoint_descriptor epx;
7092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_config_bundle const_bundle = {
7102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.config = {
7112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bLength	= sizeof(struct usb_config_descriptor),
7122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bDescriptorType	= USB_DT_CONFIG,
7132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.wTotalLength	= sizeof(struct usb_config_descriptor) +
7142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				sizeof(struct usb_interface_descriptor) +
7152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				sizeof(struct usb_endpoint_descriptor) *
7162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				USB_NUM_ENDPOINTS,
7172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bNumInterfaces		= 1,
7182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bConfigurationValue	= 1,
7192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.iConfiguration		= 0,
7202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bmAttributes		= USB_CONFIG_ATT_ONE,
7212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bMaxPower		= 0x80
7222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		},
7232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.interface = {
7242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bLength	= sizeof(struct usb_interface_descriptor),
7252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bDescriptorType	= USB_DT_INTERFACE,
7262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bInterfaceNumber	= 0,
7272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bAlternateSetting	= 0,
7282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bNumEndpoints		= USB_NUM_ENDPOINTS,
7292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bInterfaceClass	= USB_CLASS_VENDOR_SPEC,
7302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bInterfaceSubClass	= 0x42,
7312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.bInterfaceProtocol	= 0x03,
7322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			.iInterface		= 0
7332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
7342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	};
7352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* avoid to hang on accessing unaligned memory */
7372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_endpoint_descriptor const_ep1 = {
7382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bLength	= sizeof(struct usb_endpoint_descriptor),
7392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bDescriptorType	= USB_DT_ENDPOINT,
7402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bEndpointAddress	= 0x81,
7412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
7422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.wMaxPacketSize		= 0,
7432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bInterval		= 0
7442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	};
7452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_endpoint_descriptor const_ep2 = {
7472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bLength	= sizeof(struct usb_endpoint_descriptor),
7482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bDescriptorType	= USB_DT_ENDPOINT,
7492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bEndpointAddress	= 0x01,
7502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bmAttributes		= USB_ENDPOINT_XFER_BULK,
7512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.wMaxPacketSize		= 0,
7522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bInterval		= 1
7532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	};
7542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct usb_device_descriptor const_device = {
7562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bLength		= sizeof(struct usb_device_descriptor),
7572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bDescriptorType	= USB_DT_DEVICE,
7582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bcdUSB			= 0x0200,
7592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bDeviceClass		= 0,
7602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bDeviceClass		= 0,
7612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bDeviceProtocol	= 0,
7622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bMaxPacketSize0	= 0x40,
7632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.idVendor		= 0x18d1,
7642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.idProduct		= 0xd00d,
7652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bcdDevice		= 0x0100,
7662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.iManufacturer		= 1,
7672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.iProduct		= 2,
7682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.iSerialNumber		= 3,
7692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		.bNumConfigurations	= 1
7702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	};
7712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	memcpy(&config_bundle, &const_bundle, sizeof(struct usb_config_bundle));
7732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	memcpy(&config_bundle.ep1, &const_ep1, sizeof(struct usb_endpoint_descriptor));
7742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	memcpy(&config_bundle.ep2, &const_ep2, sizeof(struct usb_endpoint_descriptor));
7752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	memcpy(&device_descriptor, &const_device,
7762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		sizeof(struct usb_device_descriptor));
7772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	switch (req->request) {
7792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_GET_STATUS:
7802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (req->type == USB_DIR_IN)
7812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			ctrl_resp[0] = 1;
7822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		else
7832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			ctrl_resp[0] = 0;
7842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ctrl_resp[1] = 0;
7852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		addr = ctrl_resp;
7862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		size = 2;
7872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
7882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_CLEAR_FEATURE:
7902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if ((req->type == USB_RECIP_ENDPOINT) &&
7912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		    (req->value == USB_ENDPOINT_HALT))
7922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			usb_drv_stall(req->index & 0xf, 0, req->index >> 7);
7932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		size = 0;
7942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
7952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
7962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_SET_FEATURE:
7972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		size = 0;
7982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
7992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_SET_ADDRESS:
8012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		size = 0;
8022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_cancel_all_transfers();     // all endpoints reset
8032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_set_address(req->value);   // set device address
8042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
8052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_GET_DESCRIPTOR:
8072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("USB_REQ_GET_DESCRIPTOR: 0x%x\n", req->value >> 8);
8082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		switch (req->value >> 8) {
8092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		case USB_DT_DEVICE:
8102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			addr = &device_descriptor;
8112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			size = sizeof(device_descriptor);
8122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("Get device descriptor.\n");
8132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
8142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		case USB_DT_OTHER_SPEED_CONFIG:
8162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		case USB_DT_CONFIG:
8172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if ((req->value >> 8) == USB_DT_CONFIG) {
8182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				maxpacket = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;
8192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				config_bundle.config.bDescriptorType = USB_DT_CONFIG;
8202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			} else {
8212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				maxpacket = usb_drv_port_speed() ? 64 : USB_BLOCK_HIGH_SPEED_SIZE;
8222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				config_bundle.config.bDescriptorType = USB_DT_OTHER_SPEED_CONFIG;
8232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
8242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/* avoid hang when access unaligned structure */
8252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			memcpy(&epx, &config_bundle.ep1, sizeof(struct usb_endpoint_descriptor));
8262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			epx.wMaxPacketSize = maxpacket;
8272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			memcpy(&config_bundle.ep1, &epx, sizeof(struct usb_endpoint_descriptor));
8282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			memcpy(&epx, &config_bundle.ep2, sizeof(struct usb_endpoint_descriptor));
8292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			epx.wMaxPacketSize = maxpacket;
8302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			memcpy(&config_bundle.ep2, &epx, sizeof(struct usb_endpoint_descriptor));
8312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			addr = &config_bundle;
8322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			size = sizeof(config_bundle);
8332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("Get config descriptor.\n");
8342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
8352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		case USB_DT_STRING:
8372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			switch (req->value & 0xff) {
8382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			case 0:
8392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				addr = &lang_descriptor;
8402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				size = lang_descriptor.bLength;
8412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				break;
8422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			case 1:
8432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				addr = &string_devicename;
8442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				size = 14;
8452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				break;
8462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			case 2:
8472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				addr = &string_devicename;
8482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				size = string_devicename.bLength;
8492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				break;
8502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			case 3:
851b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang				serialno = load_serialno();
852b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang				if (serialno == NULL) {
853b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					addr = &serial_string_descriptor;
854b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					size = serial_string_descriptor.bLength;
855b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang				} else {
856b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					i = 0;
857b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					memcpy((void *)&serial_string,
858b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					       (void *)&serial_string_descriptor,
859b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					       sizeof(serial_string));
860b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					while (1) {
861b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang						serial_string.wString[i] = serialno[i];
862b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang						if (serialno[i] == '\0')
863b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang							break;
864b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang						i++;
865b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					}
866b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					addr = &serial_string;
867b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang					size = serial_string.bLength;
868b90a668aabe56b07d93b27d9ef914a5d6cbbc41eHaojian Zhuang				}
8692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				break;
8702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			default:
8712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				break;
8722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
8732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
8742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		default:
8762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
8772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
8782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
8792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_GET_CONFIGURATION:
8812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ctrl_resp[0] = 1;
8822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		addr = ctrl_resp;
8832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		size = 1;
8842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
8852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	case USB_REQ_SET_CONFIGURATION:
8872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_cancel_all_transfers();     // call reset_endpoints  reset all EPs
8882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
8892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_OUT);
8902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_request_endpoint(USB_ENDPOINT_XFER_BULK, USB_DIR_IN);
8912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/*
8922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * 0x10088800:
8932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * 1:EP enable; 8:EP type:BULK; 8:USB Active Endpoint; 8:Next Endpoint
8942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 */
8952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DIEPCTL1) | 0x10088800;
8962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPCTL1, data);
8972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DIEPCTL(1)) | 0x08000000;
8982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPCTL(1), data);
8992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* Enable interrupts on all endpoints */
9012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DAINTMSK, 0xffffffff);
9022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_status(req->value? 1 : 0, usb_drv_port_speed() ? 1 : 0);
9042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		size = 0;
9052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("Set config descriptor.\n");
9062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* USB ö�ٳɹ���,���ϱ�ʶ */
9082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		g_usb_enum_flag = 1;
9092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
9102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	default:
9122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		break;
9132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
9142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!size) {
9162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_send_nonblocking(0, 0, 0);  // send an empty packet
9172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if (size == -1) { // stall:Applies to non-control, non-isochronous IN and OUT endpoints only.
9182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_stall(0, 1, 1);     // IN
9192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_stall(0, 1, 0);     // OUT
9202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else { // stall:Applies to control endpoints only.
9212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_stall(0, 0, 1);     // IN
9222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_stall(0, 0, 0);     // OUT
9232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_drv_send_nonblocking(0, addr, size > req->length ? req->length : size);
9252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
9262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
9272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang/* IRQ handler */
9292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usb_poll(void)
9302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
9312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	uint32_t ints;
9322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	uint32_t epints, data;
9332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ints = mmio_read_32(GINTSTS);		/* interrupt status */
9352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if ((ints & 0xc3010) == 0)
9382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
9392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
9402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * bus reset
9412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * The core sets this bit to indicate that a reset is detected on the USB.
9422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
9432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (ints & GINTSTS_USBRST) {
9442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("bus reset intr\n");
9452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/*set Non-Zero-Length status out handshake */
9462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/*
9472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * DCFG:This register configures the core in Device mode after power-on
9482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * or after certain control commands or enumeration. Do not make changes
9492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * to this register after initial programming.
9502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * Send a STALL handshake on a nonzero-length status OUT transaction and
9512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * do not send the received OUT packet to the application.
9522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 */
9532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DCFG, 0x800004);
9542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		reset_endpoints();
9552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
9562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
9572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * enumeration done, we now know the speed
9582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * The core sets this bit to indicate that speed enumeration is complete. The
9592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * application must read the Device Status (DSTS) register to obtain the
9602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * enumerated speed.
9612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
9622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (ints & GINTSTS_ENUMDONE) {
9632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* Set up the maximum packet sizes accordingly */
9642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		uint32_t maxpacket = usb_drv_port_speed() ? USB_BLOCK_HIGH_SPEED_SIZE : 64;  // high speed maxpacket=512
9652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("enum done intr. Maxpacket:%d\n", maxpacket);
9662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//Set Maximum In Packet Size (MPS)
9672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DIEPCTL1) & ~0x000003ff;
9682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPCTL1, data | maxpacket);
9692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//Set Maximum Out Packet Size (MPS)
9702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(DOEPCTL1) & ~0x000003ff;
9712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DOEPCTL1, data | maxpacket);
9722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
9732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
9752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * IN EP event
9762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * The core sets this bit to indicate that an interrupt is pending on one of the IN
9772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * endpoints of the core (in Device mode). The application must read the
9782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * Device All Endpoints Interrupt (DAINT) register to determine the exact
9792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * number of the IN endpoint on which the interrupt occurred, and then read
9802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to
9812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * determine the exact cause of the interrupt. The application must clear the
9822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * appropriate status bit in the corresponding DIEPINTn register to clear this bit.
9832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
9842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (ints & GINTSTS_IEPINT) {
9852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		epints = mmio_read_32(DIEPINT0);
9862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		mmio_write_32(DIEPINT0, epints);
9872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
9882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//VERBOSE("IN EP event,ints:0x%x, DIEPINT0:%x, DAINT:%x, DAINTMSK:%x.\n",
9892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//	ints, epints, mmio_read_32(DAINT), mmio_read_32(DAINTMSK));
9902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (epints & 0x1) { /* Transfer Completed Interrupt (XferCompl) */
9912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("TX completed.DIEPTSIZ(0) = 0x%x.\n", mmio_read_32(DIEPTSIZ0));
9922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/*FIXME,Maybe you can use bytes*/
9932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/*int bytes = endpoints[0].size - (DIEPTSIZ(0) & 0x3FFFF);*/ //actual transfer
9942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (endpoints[0].busy) {
9952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[0].busy = 0;//false
9962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[0].rc = 0;
9972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[0].done = 1;//true
9982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
9992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
10002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (epints & 0x4) { /* AHB error */
10012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			WARN("AHB error on IN EP0.\n");
10022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
10032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
10042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (epints & 0x8) { /* Timeout */
10052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			WARN("Timeout on IN EP0.\n");
10062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (endpoints[0].busy) {
10072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[0].busy = 1;//false
10082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[0].rc = 1;
10092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				endpoints[0].done = 1;//true
10102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
10112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
10122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
10132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
10142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*
10152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * OUT EP event
10162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * The core sets this bit to indicate that an interrupt is pending on one of the
10172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * OUT endpoints of the core (in Device mode). The application must read the
10182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * Device All Endpoints Interrupt (DAINT) register to determine the exact
10192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * number of the OUT endpoint on which the interrupt occurred, and then read
10202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register
10212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * to determine the exact cause of the interrupt. The application must clear the
10222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 * appropriate status bit in the corresponding DOEPINTn register to clear this bit.
10232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	 */
10242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (ints & GINTSTS_OEPINT) {
10252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		/* indicates the status of an endpoint
10262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		 * with respect to USB- and AHB-related events. */
10272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		epints = mmio_read_32(DOEPINT(0));
10282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//VERBOSE("OUT EP event,ints:0x%x, DOEPINT0:%x, DAINT:%x, DAINTMSK:%x.\n",
10292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		//	ints, epints, mmio_read_32(DAINT), mmio_read_32(DAINTMSK));
10302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (epints) {
10312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPINT(0), epints);
10322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/* Transfer completed */
10332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (epints & DXEPINT_XFERCOMPL) {
10342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				/*FIXME,need use bytes*/
10352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				VERBOSE("EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n",
10362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					mmio_read_32(DOEPTSIZ(0)));
10372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				if (endpoints[0].busy) {
10382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					endpoints[0].busy = 0;
10392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					endpoints[0].rc = 0;
10402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					endpoints[0].done = 1;
10412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				}
10422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
10432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (epints & DXEPINT_AHBERR) { /* AHB error */
10442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				WARN("AHB error on OUT EP0.\n");
10452cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
10462cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
10472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/*
10482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
10492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
10502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * was empty. This interrupt is asserted on the endpoint for which the IN token
10512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * was received.
10522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 */
10532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (epints & DXEPINT_SETUP) { /* SETUP phase done */
10542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				VERBOSE("Setup phase \n");
10552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				data = mmio_read_32(DIEPCTL(0)) | DXEPCTL_SNAK;
10562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				mmio_write_32(DIEPCTL(0), data);
10572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				data = mmio_read_32(DOEPCTL(0)) | DXEPCTL_SNAK;
10582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				mmio_write_32(DOEPCTL(0), data);
10592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				/*clear IN EP intr*/
10602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				mmio_write_32(DIEPINT(0), ~0);
10612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				usb_handle_control_request((setup_packet *)&ctrl_req);
10622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
10632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
10642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/* Make sure EP0 OUT is set up to accept the next request */
10652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/* memset(p_ctrlreq, 0, NUM_ENDPOINTS*8); */
10662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			data = DOEPTSIZ0_SUPCNT(3) | DOEPTSIZ0_PKTCNT |
10672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				(64 << DOEPTSIZ0_XFERSIZE_SHIFT);
10682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPTSIZ0, data);
10692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/*
10702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * IN Token Received When TxFIFO is Empty (INTknTXFEmp)
10712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic)
10722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * was empty. This interrupt is asserted on the endpoint for which the IN token
10732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 * was received.
10742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			 */
10752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			// notes that:the compulsive conversion is expectable.
10762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			// Holds the start address of the external memory for storing or fetching endpoint data.
10772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.bs = 0x3;
10782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.mtrf = 0;
10792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.sr = 0;
10802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.l = 1;
10812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.ioc = 1;
10822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.sp = 0;
10832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.bytes = 64;
10842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.buf = (uintptr_t)&ctrl_req;
10852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.sts = 0;
10862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			dma_desc_ep0.status.b.bs = 0x0;
10872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPDMA0, (uintptr_t)&dma_desc_ep0);
10882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			// endpoint enable; clear NAK
10892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPCTL0, 0x84000000);
10902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
10912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
10922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		epints = mmio_read_32(DOEPINT1);
10932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if(epints) {
10942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			mmio_write_32(DOEPINT1, epints);
10952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("OUT EP1: epints :0x%x,DOEPTSIZ1 :0x%x.\n",epints, mmio_read_32(DOEPTSIZ1));
10962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			/* Transfer Completed Interrupt (XferCompl);Transfer completed */
10972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (epints & DXEPINT_XFERCOMPL) {
10982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				/* ((readl(DOEPTSIZ(1))) & 0x7FFFF is Transfer Size (XferSize) */
10992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				/*int bytes = (p_endpoints + 1)->size - ((readl(DOEPTSIZ(1))) & 0x7FFFF);*/
11002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				int bytes = rx_desc_bytes - dma_desc.status.b.bytes;
11012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				VERBOSE("OUT EP1: recv %d bytes \n",bytes);
11022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				if (endpoints[1].busy) {
11032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					endpoints[1].busy = 0;
11042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					endpoints[1].rc = 0;
11052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					endpoints[1].done = 1;
11062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					rx_req.complete(bytes, 0);
11072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				}
11082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
11092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (epints & DXEPINT_AHBERR) { /* AHB error */
11112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				WARN("AHB error on OUT EP1.\n");
11122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
11132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (epints & DXEPINT_SETUP) { /* SETUP phase done */
11142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				WARN("SETUP phase done  on OUT EP1.\n");
11152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			}
11162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
11172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
11182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* write to clear interrupts */
11192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GINTSTS, ints);
11202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
11212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define EYE_PATTERN	0x70533483
11232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang/*
11252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang* pico phy exit siddq, nano phy enter siddq,
11262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang* and open the clock of pico phy and dvc,
11272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang*/
11282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void dvc_and_picophy_init_chip(void)
11292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
11302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned int data;
11312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* enable USB clock */
113319f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_USBOTG);
11342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	do {
11352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
113619f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	} while ((data & PERI_CLK0_USBOTG) == 0);
11372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* out of reset */
11402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(PERI_SC_PERIPH_RSTDIS0,
114119f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan		      PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
114219f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan		      PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K);
11432cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	do {
11442cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
114519f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan		data &= PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
114619f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan			PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K;
11472cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} while (data);
11482cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11492cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(PERI_SC_PERIPH_CTRL8, EYE_PATTERN);
11502cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* configure USB PHY */
11522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(PERI_SC_PERIPH_CTRL4);
11532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* make PHY out of low power mode */
115419f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	data &= ~PERI_CTRL4_PICO_SIDDQ;
11552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* detect VBUS by external circuit, switch D+ to 1.5KOhm pullup */
115619f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	data |= PERI_CTRL4_PICO_VBUSVLDEXTSEL | PERI_CTRL4_PICO_VBUSVLDEXT;
115719f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	data &= ~PERI_CTRL4_FPGA_EXT_PHY_SEL;
11582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* select PHY */
115919f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	data &= ~PERI_CTRL4_OTG_PHY_SEL;
11602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(PERI_SC_PERIPH_CTRL4, data);
11612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	udelay(1000);
11632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	data = mmio_read_32(PERI_SC_PERIPH_CTRL5);
116519f72d7f8125d9c6283f8851f7ddc07ea2a7b213Leo Yan	data &= ~PERI_CTRL5_PICOPHY_BC_MODE;
11662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(PERI_SC_PERIPH_CTRL5, data);
1167a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj
11682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	udelay(20000);
11692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
11702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangint init_usb(void)
11722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
11732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	static int init_flag = 0;
11742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	uint32_t	data;
11752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (init_flag == 0) {
11772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		memset(&ctrl_req, 0, sizeof(setup_packet));
11782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		memset(&ctrl_resp, 0, 2);
11792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		memset(&endpoints, 0, sizeof(struct ep_type) * NUM_ENDPOINTS);
11802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		memset(&dma_desc, 0, sizeof(struct dwc_otg_dev_dma_desc));
11812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		memset(&dma_desc_ep0, 0, sizeof(struct dwc_otg_dev_dma_desc));
11822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		memset(&dma_desc_in, 0, sizeof(struct dwc_otg_dev_dma_desc));
11832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
11842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("Pico PHY and DVC init start.\n");
11862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	dvc_and_picophy_init_chip();
11882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("Pico PHY and DVC init done.\n");
11892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* wait for OTG AHB master idle */
11912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	do {
11922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		data = mmio_read_32(GRSTCTL) & GRSTCTL_AHBIDLE;
11932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} while (data == 0);
11942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("Reset usb controller\n");
11952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* OTG: Assert software reset */
11972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	mmio_write_32(GRSTCTL, GRSTCTL_CSFTRST);
11982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
11992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* wait for OTG to ack reset */
12002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	while (mmio_read_32(GRSTCTL) & GRSTCTL_CSFTRST);
12012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/* wait for OTG AHB master idle */
12032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	while ((mmio_read_32(GRSTCTL) & GRSTCTL_AHBIDLE) == 0);
12042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("Reset usb controller done\n");
12062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	usb_config();
12082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("exit usb_init()\n");
12092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return 0;
12102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
12112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define LOCK_STATE_LOCKED		0
12132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define LOCK_STATE_UNLOCKED		1
12142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang#define LOCK_STATE_RELOCKED		2
12152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12163da0f46f461e4927a67646685552cf096db7aa53Haojian Zhuang#define FB_MAX_FILE_SIZE		(256 * 1024 * 1024)
12172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic struct ptentry *flash_ptn = NULL;
12192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void fb_getvar(char *cmdbuf)
12212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
12222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	char response[64];
12232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	char part_name[32];
12242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int bytes;
12252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	struct ptentry *ptn = 0;
12262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!strncmp(cmdbuf + 7, "max-download-size", 17)) {
12282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		bytes = sprintf(response, "OKAY0x%08x",
12292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				FB_MAX_FILE_SIZE);
12302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		response[bytes] = '\0';
12312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		tx_status(response);
12322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_cmd();
12332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if (!strncmp(cmdbuf + 7, "partition-type:", 15)) {
12342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		bytes = sprintf(part_name, "%s", cmdbuf + 22);
12352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		ptn = find_ptn(part_name);
12362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (ptn == NULL) {
12372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			bytes = sprintf(response, "FAIL%s",
12382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					"invalid partition");
12392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			response[bytes] = '\0';
12402cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			flash_ptn = NULL;
12412cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		} else {
12422cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			flash_ptn = ptn;
1243a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj			if (!strncmp(cmdbuf +22, "system", 6) || !strncmp(cmdbuf +22, "userdata", 8) ||
1244a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj				!strncmp(cmdbuf +22, "cache", 5)) {
1245a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj				bytes = sprintf(response, "OKAYext4");
1246a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj				response[bytes] = '\0';
1247a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj			} else {
1248a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj				bytes = sprintf(response, "OKAYraw");
1249a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj				response[bytes] = '\0';
1250a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj			}
12512cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
12522cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		tx_status(response);
12532cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_cmd();
1254a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj        } else if (!strncmp(cmdbuf + 7, "partition-size:", 15)) {
1255a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                bytes = sprintf(part_name, "%s", cmdbuf + 22);
1256a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                ptn = find_ptn(part_name);
1257a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                if (ptn == NULL) {
1258a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                        bytes = sprintf(response, "FAIL%s",
1259a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                                        "invalid partition");
1260a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                        response[bytes] = '\0';
1261a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                        flash_ptn = NULL;
1262a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                } else {
1263a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                        bytes = sprintf(response, "OKAY%llx",ptn->length);
1264a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                        response[bytes] = '\0';
1265a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                        flash_ptn = ptn;
1266a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                }
1267a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                tx_status(response);
1268a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj                rx_cmd();
1269b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	} else if (!strncmp(cmdbuf + 7, "serialno", 8)) {
1270b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		bytes = sprintf(response, "OKAY%s",
1271b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang				load_serialno());
1272b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		response[bytes] = '\0';
1273b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		tx_status(response);
1274b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		rx_cmd();
1275a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj	} else if (!strncmp(cmdbuf + 7, "version-bootloader", 18)) {
1276554b28ac1d6a6c75893fb5831107fee464ce581dVishal Bhoj		bytes = sprintf(response, "OKAY%s", VERSION_BOOTLOADER);
1277a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		response[bytes] = '\0';
1278a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		tx_status(response);
1279a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		rx_cmd();
1280a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj	} else if (!strncmp(cmdbuf + 7, "version-baseband", 16)) {
1281a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		bytes = sprintf(response, "OKAYN/A");
1282a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		response[bytes] = '\0';
1283a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		tx_status(response);
1284a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		rx_cmd();
1285a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj	} else if (!strncmp(cmdbuf + 7, "product", 8)) {
12862111fbe1ea0a227c52069689221a95de913fc927Dmitry Shmidt		bytes = sprintf(response, "OKAYhikey");
1287a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		response[bytes] = '\0';
1288a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		tx_status(response);
1289a1d0a7b097cefec3b4bedc8fa2212bdd9a5033f7Vishal Bhoj		rx_cmd();
12902190a7195ed2aed0d52958d92e3c405bc4245112John Stultz	} else {
12912190a7195ed2aed0d52958d92e3c405bc4245112John Stultz		bytes = sprintf(response, "FAIL%s",
12922190a7195ed2aed0d52958d92e3c405bc4245112John Stultz					"unknown var");
12932190a7195ed2aed0d52958d92e3c405bc4245112John Stultz		response[bytes] = '\0';
12942190a7195ed2aed0d52958d92e3c405bc4245112John Stultz		tx_status(response);
12952190a7195ed2aed0d52958d92e3c405bc4245112John Stultz		rx_cmd();
12962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
12972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
12982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
12992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang/* FIXME: do not support endptr yet */
13002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned long strtoul(const char *nptr, char **endptr, int base)
13012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
13022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	unsigned long step, data;
13032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int i;
13042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (base == 0)
13062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		step = 10;
13072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	else if ((base < 2) || (base > 36)) {
13082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		VERBOSE("%s: invalid base %d\n", __func__, base);
13092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return 0;
13102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else
13112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		step = base;
13122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	for (i = 0, data = 0; ; i++) {
13142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (nptr[i] == '\0')
13152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			break;
13162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		else if (!isalpha(nptr[i]) && !isdigit(nptr[i])) {
13172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("%s: invalid string %s at %d [%x]\n",
13182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				__func__, nptr, i, nptr[i]);
13192cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			return 0;
13202cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		} else {
13212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			data *= step;
13222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			if (isupper(nptr[i]))
13232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				data += nptr[i] - 'A' + 10;
13242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			else if (islower(nptr[i]))
13252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				data += nptr[i] - 'a' + 10;
13262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			else if (isdigit(nptr[i]))
13272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				data += nptr[i] - '0';
13282cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
13292cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
13302cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	return data;
13312cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
13322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13338a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuangstatic void fb_serialno(char *cmdbuf)
13348a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang{
13358a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang	struct random_serial_num random;
13368a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang
13378a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang	generate_serialno(&random);
13388a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang	flush_random_serialno((unsigned long)&random, sizeof(random));
13398a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang}
13408a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang
1341b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuangstatic int fb_assigned_sn(char *cmdbuf)
1342b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang{
1343b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	struct random_serial_num random;
1344b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	int ret;
1345b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang
1346b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	ret = assign_serialno(cmdbuf, &random);
1347b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	if (ret < 0)
1348b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		return ret;
1349b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	flush_random_serialno((unsigned long)&random, sizeof(random));
1350b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang	return 0;
1351b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang}
1352b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang
13533da0f46f461e4927a67646685552cf096db7aa53Haojian Zhuang#define FB_DOWNLOAD_BASE	0x20000000
13542cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13552cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic unsigned long fb_download_base, fb_download_size;
13562cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13572cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void fb_download(char *cmdbuf)
13582cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
13592cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	char response[64];
13602cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	int bytes;
13612cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13622cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (!flash_ptn) {
13632cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		bytes = sprintf(response, "FAIL%s",
13642cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				"invalid partition");
13652cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		response[bytes] = '\0';
13662cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		tx_status(response);
13672cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_cmd();
13682cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else {
13692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_addr = FB_DOWNLOAD_BASE;
13702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		rx_length = strtoul(cmdbuf + 9, NULL, 16);
13712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		fb_download_base = rx_addr;
13722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		fb_download_size = rx_length;
13732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		if (rx_length > FB_MAX_FILE_SIZE) {
13742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			bytes = sprintf(response, "FAIL%s",
13752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					"file is too large");
13762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			response[bytes] = '\0';
13772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			tx_status(response);
13782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			rx_cmd();
13792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		} else {
13802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			bytes = sprintf(response, "DATA%08x",
13812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang					rx_length);
13822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			VERBOSE("start:0x%x, length:0x%x, res:%s\n",
13832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang				rx_addr, rx_length, response);
13842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			response[bytes] = '\0';
13852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			tx_status(response);
13862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang			rx_data();
13872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		}
13882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
13892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
13902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void fb_flash(char *cmdbuf)
13922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
13932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	flush_user_images(cmdbuf + 6, fb_download_base, fb_download_size);
13942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	tx_status("OKAY");
13952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	rx_cmd();
13962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
13972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
13987a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuangstatic void fb_reboot(char *cmdbuf)
13997a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang{
14007a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang	/* Send the system reset request */
14017a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang	mmio_write_32(AO_SC_SYS_STAT0, 0x48698284);
14027a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang
14037a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang	wfi();
14047a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang	panic();
14057a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang}
14067a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang
14072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usb_rx_cmd_complete(unsigned actual, int stat)
14082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
14092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if(stat != 0) return;
14102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if(actual > 4095)
14122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		actual = 4095;
14132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cmdbuf[actual] = 0;
14142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	INFO("cmd :%s\n",cmdbuf);
14162cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14172cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if(memcmp(cmdbuf, (void *)"reboot", 6) == 0) {
14182cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		tx_status("OKAY");
14197a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang		fb_reboot(cmdbuf);
14207a0e1dd0f7ad4ba3137dcba1ca833502c535d7b8Haojian Zhuang		return;
14212cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if (!memcmp(cmdbuf, (void *)"getvar:", 7)) {
14222cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		fb_getvar(cmdbuf);
14232cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
14242cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if (!memcmp(cmdbuf, (void *)"download:", 9)) {
14252cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		fb_download(cmdbuf);
14262cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
14272cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if(memcmp(cmdbuf, (void *)"erase:", 6) == 0) {
14287f58aa36c7b4215c289f4e7e1ff2175462dfb601Vishal Bhoj                /* FIXME erase is not supported but we return success */
14297f58aa36c7b4215c289f4e7e1ff2175462dfb601Vishal Bhoj                tx_status("OKAY");
14307f58aa36c7b4215c289f4e7e1ff2175462dfb601Vishal Bhoj                rx_cmd();
14317f58aa36c7b4215c289f4e7e1ff2175462dfb601Vishal Bhoj                return;
14322cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if(memcmp(cmdbuf, (void *)"flash:", 6) == 0) {
14332cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		INFO("recog updatefile\n");
14342cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		fb_flash(cmdbuf);
14352cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
14362cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	} else if(memcmp(cmdbuf, (void *)"boot", 4) == 0) {
14372cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		INFO(" - OKAY\n");
14382cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14392cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		return;
14408a372351b7c5794c05e4a69bf1fae35b8c110fcbHaojian Zhuang	} else if (memcmp(cmdbuf, (void *)"oem serialno", 12) == 0) {
1441b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		if (*(cmdbuf + 12) == '\0') {
1442b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang			fb_serialno(cmdbuf);
1443b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang			tx_status("OKAY");
1444b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang			rx_cmd();
1445b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang			return;
1446b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		} else if (memcmp(cmdbuf + 12, (void *)" set", 4) == 0) {
1447b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang			if (fb_assigned_sn(cmdbuf + 16) == 0) {
1448b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang				tx_status("OKAY");
1449b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang				rx_cmd();
1450b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang				return;
1451b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang			}
1452b85b3f3717ec3b0af0a2e992f01d533e31e90803Haojian Zhuang		}
145359fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang	} else if (memcmp(cmdbuf, (void *)"oem led", 7) == 0) {
145459fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang		if ((*(cmdbuf + 7) >= '1') && (*(cmdbuf + 7) <= '4')) {
145559fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang			int led;
145659fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang			led = *(cmdbuf + 7) - '0';
145759fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang			if (memcmp(cmdbuf + 8, (void *)" on", 3) == 0) {
145859fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				gpio_set_value(31 + led, 1);
145959fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				tx_status("OKAY");
146059fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				rx_cmd();
146159fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				return;
146259fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang			} else if (memcmp(cmdbuf + 8, (void *)" off", 4) == 0) {
146359fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				gpio_set_value(31 + led, 0);
146459fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				tx_status("OKAY");
146559fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				rx_cmd();
146659fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang				return;
146759fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang			}
146859fe132c49f99af8ef1969f13a94ba850e72b6a5Haojian Zhuang		}
14692cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
14702cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14712cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	tx_status("FAILinvalid command");
14722cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	rx_cmd();
14732cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
14742cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14752cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangstatic void usbloader_init(void)
14762cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
14772cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("enter usbloader_init\n");
14782cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14792cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*usb sw and hw init*/
14802cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	init_usb();
14812cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14822cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	/*alloc and init sth for transfer*/
14832cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1in.num = BULK_IN_EP;
14842cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1in.in = 1;
14852cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1in.req = NULL;
14862cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1in.maxpkt = MAX_PACKET_LEN;
14872cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1in.next = &ep1in;
14882cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1out.num = BULK_OUT_EP;
14892cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1out.in = 0;
14902cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1out.req = NULL;
14912cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1out.maxpkt = MAX_PACKET_LEN;
14922cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	ep1out.next = &ep1out;
14932cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	cmdbuf = (char *)(rx_req.buf);
14942cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14952cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	VERBOSE("exit usbloader_init\n");
14962cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
14972cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
14982cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_reinit()
14992cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
15002cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	if (usb_need_reset)
15012cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	{
15022cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_need_reset = 0;
15032cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		init_usb();
15042cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
15052cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
15062cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang
15072cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuangvoid usb_download(void)
15082cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang{
15092cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	usbloader_init();
15102cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	INFO("Enter downloading mode. Please run fastboot command on Host.\n");
15112cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	for (;;) {
15122cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_poll();
15132cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang		usb_reinit();
15142cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang	}
15152cb2f7e3b5aa150d70afc5fcf574265c68491063Haojian Zhuang}
1516