| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329 |
- /*
- * Copyright (c) 2012 MediaTek Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #include <sys/types.h>
- #include <string.h>
- #include <stdlib.h>
- #include <debug.h>
- #include <reg.h>
- #include <platform/bitops.h>
- #include <platform/mt_irq.h>
- #include <platform/mt_reg_base.h>
- #include <platform/mt_usb.h>
- #include <platform/mt_typedefs.h>
- #include <platform/timer.h>
- #include <kernel/thread.h>
- #include <platform/sec_devinfo.h>
- #include <dev/udc.h>
- #ifdef MACH_FPGA
- #define CFG_FPGA_PLATFORM (1)
- #else
- #define DBG_PHY_CALIBRATION 1
- #endif
- #define USB_DOUBLE_BUF
- #define USB_GINTR
- #ifdef USB_DEBUG
- /* DEBUG INFO Sections */
- #define DBG_USB_DUMP_DESC 0
- #define DBG_USB_DUMP_DATA 0
- #define DBG_USB_DUMP_SETUP 1
- #define DBG_USB_FIFO 0
- #define DBG_USB_GENERAL 1
- #define DBG_PHY_CALIBRATION 0
- #endif
- #define DBG_C(x...) dprintf(CRITICAL, x)
- #define DBG_I(x...) dprintf(INFO, x)
- #define DBG_S(x...) dprintf(SPEW, x)
- #if DBG_USB_GENERAL
- #define DBG_IRQ(x...) dprintf(INFO, x)
- #else
- #define DBG_IRQ(x...) do{} while(0)
- #endif
- /* bits used in all the endpoint status registers */
- #define EPT_TX(n) (1 << ((n) + 16))
- #define EPT_RX(n) (1 << (n))
- /* udc.h wrapper for usbdcore */
- static unsigned char usb_config_value = 0;
- EP0_STATE ep0_state = EP0_IDLE;
- int set_address = 0;
- u32 fifo_addr = FIFO_ADDR_START;
- #define EP0 0
- /* USB transfer directions */
- #define USB_DIR_IN DEVICE_WRITE /* val: 0x80 */
- #define USB_DIR_OUT DEVICE_READ /* val: 0x00 */
- #define EP0_MAX_PACKET_SIZE 64
- /* Request types */
- #define USB_TYPE_STANDARD (0x00 << 5)
- #define USB_TYPE_CLASS (0x01 << 5)
- #define USB_TYPE_VENDOR (0x02 << 5)
- #define USB_TYPE_RESERVED (0x03 << 5)
- /* values used in GET_STATUS requests */
- #define USB_STAT_SELFPOWERED 0x01
- /* USB recipients */
- #define USB_RECIP_DEVICE 0x00
- #define USB_RECIP_INTERFACE 0x01
- #define USB_RECIP_ENDPOINT 0x02
- #define USB_RECIP_OTHER 0x03
- /* Endpoints */
- #define USB_EP_NUM_MASK 0x0f /* in bEndpointAddress */
- #define USB_EP_DIR_MASK 0x80
- #define USB_TYPE_MASK 0x60
- #define USB_RECIP_MASK 0x1f
- #if CFG_FPGA_PLATFORM
- /* for usb phy */
- #include <platform/mt_i2c.h>
- #endif
- #define URB_BUF_SIZE 512
- struct urb {
- struct udc_endpoint *endpoint;
- struct udc_device *device;
- struct setup_packet device_request;
- u8 *buffer;
- unsigned int actual_length;
- };
- static struct udc_endpoint *ep0in, *ep0out;
- static struct udc_request *ep0req;
- static unsigned char ep0_buf[4096] __attribute__((aligned(32)));
- struct urb mt_ep0_urb;
- struct urb mt_tx_urb;
- struct urb mt_rx_urb;
- struct urb *ep0_urb = &mt_ep0_urb;
- struct urb *tx_urb = &mt_tx_urb;
- struct urb *rx_urb = &mt_rx_urb;
- /* endpoint data - mt_ep */
- struct udc_endpoint {
- /* rx side */
- struct urb *rcv_urb; /* active urb */
- /* tx side */
- struct urb *tx_urb; /* active urb */
- /* info from hsusb */
- struct udc_request *req;
- unsigned int bit; /* EPT_TX/EPT_RX */
- unsigned char num;
- unsigned char in;
- unsigned short maxpkt;
- int status; /* status for error handling */
- unsigned int sent; /* data already sent */
- unsigned int last; /* data sent in last packet XXX do we need this */
- unsigned char mode; /* double buffer */
- };
- /* from mt_usbtty.h */
- #define NUM_ENDPOINTS 3
- /* origin endpoint_array */
- struct udc_endpoint ep_list[NUM_ENDPOINTS + 1]; /* one extra for control endpoint */
- static int usb_online = 0;
- static u8 dev_address = 0;
- static struct udc_device *the_device;
- static struct udc_gadget *the_gadget;
- /* end from hsusb.c */
- /* declare ept_complete handle */
- static void handle_ept_complete(struct udc_endpoint *ept);
- /* usb phy bring up */
- #if CFG_FPGA_PLATFORM
- #define USB_I2C_ID I2C0 /* 0 - 6 */
- #define PATH_NORMAL 0
- #define PATH_PMIC 1
- U32 usb_i2c_read8 (U8 addr, U8 *dataBuffer)
- {
- U32 ret_code = I2C_OK;
- // U8 write_data = addr;
- U16 len;
- static struct mt_i2c_t i2c;
- i2c.id = USB_I2C_ID;
- i2c.addr = 0x60; /* i2c API will shift-left this value to 0xc0 */
- i2c.mode = ST_MODE;
- i2c.speed = 100;
- i2c.dma_en = 0;
- len = 1;
- /* set register command */
- #if 0
- ret_code = i2c_write(&i2c, &write_data, len);
- if (ret_code != len)
- return ret_code;
- ret_code = i2c_read(&i2c, dataBuffer, len);
- #else
- ret_code = i2c_write_read(&i2c, dataBuffer, len, len);
- #endif
- return ret_code;
- }
- U32 usb_i2c_write8(U8 addr, U8 value)
- {
- U32 ret_code = I2C_OK;
- U8 write_data[2];
- U16 len;
- static struct mt_i2c_t i2c;
- write_data[0]= addr;
- write_data[1] = value;
- i2c.id = USB_I2C_ID;
- i2c.addr = 0x60; /* i2c API will shift-left this value to 0xc0 */
- i2c.mode = ST_MODE;
- i2c.speed = 100;
- i2c.dma_en = 0;
- len = 2;
- ret_code = i2c_write(&i2c, write_data, len);
- return ret_code;
- }
- #define USBPHY_I2C_READ8(addr, buffer) usb_i2c_read8(addr, buffer)
- #define USBPHY_I2C_WRITE8(addr, value) usb_i2c_write8(addr, value)
- #endif
- /* use mt_typedefs.h */
- #define USBPHY_READ8(offset) readb(USB20_PHY_BASE+offset)
- #define USBPHY_WRITE8(offset, value) writeb(value, USB20_PHY_BASE+offset)
- #define USBPHY_SET8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) | (mask))
- #define USBPHY_CLR8(offset, mask) USBPHY_WRITE8(offset, (USBPHY_READ8(offset)) & (~mask))
- #define USB11PHY_READ8(offset) readb(USB11_PHY_BASE+offset)
- #define USB11PHY_WRITE8(offset, value) writeb(value, USB11_PHY_BASE+offset)
- #define USB11PHY_SET8(offset, mask) USB11PHY_WRITE8(offset, (USB11PHY_READ8(offset)) | (mask))
- #define USB11PHY_CLR8(offset, mask) USB11PHY_WRITE8(offset, (USB11PHY_READ8(offset)) & (~mask))
- #if CFG_FPGA_PLATFORM
- void mt_usb_phy_poweron(void)
- {
- #define PHY_DRIVING 0x3
- #if defined(USB_PHY_DRIVING_TUNING)
- UINT8 usbreg8;
- unsigned int i;
- #endif
- /* force_suspendm = 0 */
- USBPHY_CLR8(0x6a, 0x04);
- USBPHY_I2C_WRITE8(0xff, 0x00);
- USBPHY_I2C_WRITE8(0x61, 0x04);
- USBPHY_I2C_WRITE8(0x68, 0x00);
- USBPHY_I2C_WRITE8(0x6a, 0x00);
- USBPHY_I2C_WRITE8(0x00, 0x6e);
- USBPHY_I2C_WRITE8(0x1b, 0x0c);
- USBPHY_I2C_WRITE8(0x08, 0x44);
- USBPHY_I2C_WRITE8(0x11, 0x55);
- USBPHY_I2C_WRITE8(0x1a, 0x68);
- #if defined(USB_PHY_DRIVING_TUNING)
- /* driving tuning */
- USBPHY_I2C_READ8(0xab, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xab, usbreg8);
- for(i = 0; i < 16; i++)
- {
- USBPHY_I2C_READ8((0x92+i), &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8((0x92+i), usbreg8);
- }
- USBPHY_I2C_READ8(0xbc, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xbc, usbreg8);
- USBPHY_I2C_READ8(0xbe, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xbe, usbreg8);
- USBPHY_I2C_READ8(0xbf, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xbf, usbreg8);
- USBPHY_I2C_READ8(0xcd, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xcd, usbreg8);
- USBPHY_I2C_READ8(0xf1, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xf1, usbreg8);
- USBPHY_I2C_READ8(0xa7, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xa7, usbreg8);
- USBPHY_I2C_READ8(0xa8, &usbreg8);
- usbreg8 &= ~0x3;
- usbreg8 |= PHY_DRIVING;
- USBPHY_I2C_WRITE8(0xa8, usbreg8);
- #endif
- udelay(800);
- }
- void mt_usb_phy_savecurrent (void)
- {
- /* no need */
- }
- void mt_usb_phy_recover (void)
- {
- /* no need */
- }
- void mt_usb11_phy_savecurrent(void)
- {
- /* no need */
- }
- void Charger_Detect_Init(void)
- {
- /* no need */
- }
- void Charger_Detect_Release(void)
- {
- /* no need */
- }
- #else
- void mt_usb_phy_poweron(void)
- {
- /*
- * swtich to USB function.
- * (system register, force ip into usb mode).
- */
- USBPHY_CLR8(0x6b, 0x04);
- USBPHY_CLR8(0x6e, 0x01);
- USBPHY_CLR8(0x21, 0x03);
- /* RG_USB20_BC11_SW_EN = 1'b0 */
- USBPHY_SET8(0x22, 0x04);
- USBPHY_CLR8(0x1a, 0x80);
- /* RG_USB20_DP_100K_EN = 1'b0 */
- /* RG_USB20_DP_100K_EN = 1'b0 */
- USBPHY_CLR8(0x22, 0x03);
- /*OTG enable*/
- USBPHY_SET8(0x20, 0x10);
- /* release force suspendm */
- USBPHY_CLR8(0x6a, 0x04);
- udelay(800);
- /* force enter device mode */
- USBPHY_CLR8(0x6c, 0x10);
- USBPHY_SET8(0x6c, 0x2E);
- USBPHY_SET8(0x6d, 0x3E);
- return;
- }
- void mt_usb_phy_savecurrent(void)
- {
- /*
- * swtich to USB function.
- * (system register, force ip into usb mode).
- */
- USBPHY_CLR8(0x6b, 0x04);
- USBPHY_CLR8(0x6e, 0x01);
- USBPHY_CLR8(0x21, 0x03);
- /* release force suspendm */
- USBPHY_CLR8(0x6a, 0x04);
- USBPHY_SET8(0x68, 0x04);
- /* RG_DPPULLDOWN./RG_DMPULLDOWN. */
- USBPHY_SET8(0x68, 0xc0);
- /* RG_XCVRSEL[1:0] = 2'b01 */
- USBPHY_CLR8(0x68, 0x30);
- USBPHY_SET8(0x68, 0x10);
- /* RG_TERMSEL = 1'b1 */
- USBPHY_SET8(0x68, 0x04);
- /* RG_DATAIN[3:0] = 4'b0000 */
- USBPHY_CLR8(0x69, 0x3c);
- /*
- * force_dp_pulldown, force_dm_pulldown,
- * force_xcversel, force_termsel.
- */
- USBPHY_SET8(0x6a, 0xba);
- /* RG_USB20_BC11_SW_EN = 1'b0 */
- USBPHY_CLR8(0x1a, 0x80);
- /* RG_USB20_OTG_VBUSSCMP_EN = 1'b0 */
- USBPHY_CLR8(0x1a, 0x10);
- udelay(800);
- USBPHY_CLR8(0x6a, 0x04);
- /* rg_usb20_pll_stable = 1 */
- //USBPHY_SET8(0x63, 0x02);
- udelay(1);
- /* force suspendm = 1 */
- //USBPHY_SET8(0x6a, 0x04);
- //udelay(1);
- return;
- }
- void mt_usb_phy_recover(void)
- {
- /* clean PUPD_BIST_EN */
- /* PUPD_BIST_EN = 1'b0 */
- /* PMIC will use it to detect charger type */
- USBPHY_CLR8(0x1d, 0x10);
- /* force_uart_en = 1'b0 */
- USBPHY_CLR8(0x6b, 0x04);
- /* RG_UART_EN = 1'b0 */
- USBPHY_CLR8(0x6e, 0x01);
- /* force_uart_en = 1'b0 */
- USBPHY_CLR8(0x6a, 0x04);
- USBPHY_CLR8(0x21, 0x03);
- USBPHY_CLR8(0x68, 0xf4);
- /* RG_DATAIN[3:0] = 4'b0000 */
- USBPHY_CLR8(0x69, 0x3c);
- USBPHY_CLR8(0x6a, 0xba);
- /* RG_USB20_BC11_SW_EN = 1'b0 */
- USBPHY_CLR8(0x1a, 0x80);
- /* RG_USB20_OTG_VBUSSCMP_EN = 1'b1 */
- USBPHY_SET8(0x1a, 0x10);
- udelay(800);
- /* force enter device mode */
- //USBPHY_CLR8(0x6c, 0x10);
- //USBPHY_SET8(0x6c, 0x2E);
- //USBPHY_SET8(0x6d, 0x3E);
- }
- void mt_usb11_phy_savecurrent(void)
- {
- #if 0
- USB11PHY_SET8(0xca, 0x10);
- USB11PHY_SET8(0xcb, 0x3c);
- USB11PHY_CLR8(0xc1, 0x08);
- USB11PHY_CLR8(0xc7, 0x06);
- USB11PHY_SET8(0xc6, 0x06);
- #endif
- }
- void Charger_Detect_Init(void)
- {
- /* RG_USB20_BC11_SW_EN = 1'b1 */
- USBPHY_SET8(0x1a, 0x80);
- }
- void Charger_Detect_Release(void)
- {
- /* RG_USB20_BC11_SW_EN = 1'b0 */
- USBPHY_CLR8(0x1a, 0x80);
- }
- #endif
- /* usb phy bring up end */
- #if !CFG_FPGA_PLATFORM
- //ALPS00427972, implement the analog register formula
- void mt_usb_phy_calibraion (int case_set, int input_reg)
- {
- #if 0
- int temp_added=0;
- int temp_test=0;
- int temp_mask;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: case_set %d, input_reg = 0x%x \n", __func__, case_set, input_reg);
- #endif
- switch(case_set)
- {
- case 1:
- //case 1
- //If M_HW_RES3[15:13] !=0
- //RG_USB20_TERM_VREF_SEL[2:0] <= RG_USB20_TERM_VREF_SEL[2:0] + M_HW_RES3[15:13]
- temp_mask = 0x07;
- temp_test = USBPHY_READ8(0x05);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_test = 0x%x \n", __func__, temp_test);
- #endif
- temp_added = (USBPHY_READ8(0x05)& temp_mask) + input_reg;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- temp_added &= 0x07;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- USBPHY_CLR8(0x05, temp_mask);
- USBPHY_SET8(0x05, temp_added);
- temp_test = USBPHY_READ8(0x05);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: final temp_test = 0x%x \n", __func__, temp_test);
- #endif
- break;
- case 2:
- //case 2
- //If M_HW_RES3[12:10] !=0
- //RG_USB20_CLKREF_REF[2:0]<= RG_USB20_CLKREF_REF[2:0]+ M_HW_RES3[12:10]
- temp_mask = 0x07;
- temp_test = USBPHY_READ8(0x07);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_test = 0x%x \n", __func__, temp_test);
- #endif
- temp_added = (USBPHY_READ8(0x07)& temp_mask) + input_reg;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- temp_added &= 0x07;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- USBPHY_CLR8(0x07, temp_mask);
- USBPHY_SET8(0x07, temp_added);
- temp_test = USBPHY_READ8(0x07);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: final temp_test = 0x%x \n", __func__, temp_test);
- #endif
- break;
- case 3:
- //case 3
- //If M_HW_RES3[9:7] !=0
- //RG_USB20_VRT_VREF_SEL[2:0]<=RG_USB20_VRT_VREF_SEL[2:0]+ M_HW_RES3[9:7]
- temp_mask = 0x70;
- temp_test = USBPHY_READ8(0x05);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_test = 0x%x \n", __func__, temp_test);
- #endif
- temp_added = (USBPHY_READ8(0x05)& temp_mask) >> 4;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- temp_added += input_reg;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- temp_added &= 0x07;
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: temp_added = 0x%x \n", __func__, temp_added);
- #endif
- USBPHY_CLR8(0x05, temp_mask);
- USBPHY_SET8(0x05, temp_added<<4);
- temp_test = USBPHY_READ8(0x05);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: final temp_test = 0x%x \n", __func__, temp_test);
- #endif
- break;
- }
- #endif
- }
- //ALPS00427972, implement the analog register formula
- #endif
- void board_usb_init(void)
- {
- mt_usb_phy_poweron();
- }
- struct udc_descriptor {
- struct udc_descriptor *next;
- unsigned short tag; /* ((TYPE << 8) | NUM) */
- unsigned short len; /* total length */
- unsigned char data[0];
- };
- #if DBG_USB_DUMP_SETUP
- static void dump_setup_packet(char *str, struct setup_packet *sp) {
- DBG_I("\n");
- DBG_I(str);
- DBG_I(" bmRequestType = %x\n", sp->type);
- DBG_I(" bRequest = %x\n", sp->request);
- DBG_I(" wValue = %x\n", sp->value);
- DBG_I(" wIndex = %x\n", sp->index);
- DBG_I(" wLength = %x\n", sp->length);
- }
- #else
- static void dump_setup_packet(char *str, struct setup_packet *sp) {}
- #endif
- static void copy_desc(struct urb *urb, void *data, int length) {
- #if DBG_USB_FIFO
- DBG_I("%s: urb: %x, data %x, length: %d, actual_length: %d\n",
- __func__, urb->buffer, data, length, urb->actual_length);
- #endif
- //memcpy(urb->buffer + urb->actual_length, data, length);
- memcpy(urb->buffer, data, length);
- //urb->actual_length += length;
- urb->actual_length = length;
- #if DBG_USB_FIFO
- DBG_I("%s: urb: %x, data %x, length: %d, actual_length: %d\n",
- __func__, urb, data, length, urb->actual_length);
- #endif
- }
- struct udc_descriptor *udc_descriptor_alloc(unsigned type, unsigned num,
- unsigned len)
- {
- struct udc_descriptor *desc;
- if ((len > 255) || (len < 2) || (num > 255) || (type > 255))
- return 0;
- if (!(desc = malloc(sizeof(struct udc_descriptor) + len)))
- return 0;
- desc->next = 0;
- desc->tag = (type << 8) | num;
- desc->len = len;
- desc->data[0] = len;
- desc->data[1] = type;
- return desc;
- }
- static struct udc_descriptor *desc_list = 0;
- static unsigned next_string_id = 1;
- void udc_descriptor_register(struct udc_descriptor *desc) {
- desc->next = desc_list;
- desc_list = desc;
- }
- unsigned udc_string_desc_alloc(const char *str)
- {
- unsigned len;
- struct udc_descriptor *desc;
- unsigned char *data;
- if (next_string_id > 255)
- return 0;
- if (!str)
- return 0;
- len = strlen(str);
- desc = udc_descriptor_alloc(TYPE_STRING, next_string_id, len * 2 + 2);
- if (!desc)
- return 0;
- next_string_id++;
- /* expand ascii string to utf16 */
- data = desc->data + 2;
- while (len-- > 0) {
- *data++ = *str++;
- *data++ = 0;
- }
- udc_descriptor_register(desc);
- return desc->tag & 0xff;
- }
- static int mt_read_fifo(struct udc_endpoint *endpoint) {
- struct urb *urb = endpoint->rcv_urb;
- int len = 0, count = 0;
- int ep_num = endpoint->num;
- int index;
- unsigned char *cp;
- u32 *wp;
- #if !CFG_FPGA_PLATFORM
- u16 dma_cntl = 0;
- #endif
- if (ep_num == EP0)
- urb = ep0_urb;
- if (urb) {
- index = readb(INDEX);
- writeb(ep_num, INDEX);
- cp = (u8 *) (urb->buffer + urb->actual_length);
- wp = (u32 *) cp;
- #if DBG_USB_FIFO
- DBG_I("%s: ep_num: %d, urb: %x, urb->buffer: %x, urb->actual_length = %d\n",
- __func__, ep_num, urb, urb->buffer, urb->actual_length);
- #endif
- count = len = readw(IECSR + RXCOUNT);
- if (ep_num != 0) {
- #if DBG_USB_FIFO
- DBG_I("%s: ep_num: %d count = %d\n",
- __func__, ep_num, count);
- #endif
- }
- /* FIX: DMA has problem write now */
- #if !CFG_FPGA_PLATFORM
- arch_clean_invalidate_cache_range((addr_t) cp, count);
- if (ep_num != 0) {
- writel((u32)wp, USB_DMA_ADDR (ep_num));
- writel(count, USB_DMA_COUNT (ep_num));
- dma_cntl =
- USB_DMA_BURST_MODE_3 | (ep_num << USB_DMA_ENDPNT_OFFSET) |
- USB_DMA_EN;
- writew(dma_cntl, USB_DMA_CNTL (ep_num));
- while (readw(USB_DMA_CNTL (ep_num)) & USB_DMA_EN);
- }
- else
- #endif
- {
- while (len > 0) {
- if (len >= 4) {
- *wp++ = readl(FIFO(ep_num));
- cp = (unsigned char *) wp;
- //DBG_I("USB READ FIFO: wp = %lu, cp = %lu\n", wp, cp);
- len -= 4;
- } else {
- *cp++ = readb(FIFO(ep_num));
- //DBG_I("USB READ FIFO: wp = %lu, cp = %lu\n", wp, cp);
- len--;
- }
- }
- }
- #if DBG_USB_DUMP_DATA
- if (ep_num != 0) {
- DBG_I("%s: &urb->buffer: %x\n", __func__, urb->buffer);
- DBG_I("[USB] dump data:\n");
- hexdump8(urb->buffer, count);
- }
- #endif
- urb->actual_length += count;
- writeb(index, INDEX);
- }
- return count;
- }
- static int mt_write_fifo(struct udc_endpoint *endpoint)
- {
- struct urb *urb = endpoint->tx_urb;
- int last = 0, count = 0;
- int ep_num = endpoint->num;
- int index;
- unsigned char *cp = NULL;
- #ifdef USB_TX_DMA_MODE_0
- u32 *wp;
- u16 dma_cntl = 0;
- #endif
- if (ep_num == EP0)
- urb = ep0_urb;
- if (urb) {
- index = readb(INDEX);
- writeb(ep_num, INDEX);
- #if DBG_USB_DUMP_DESC
- DBG_I("%s: dump desc\n", __func__);
- hexdump8(urb->buffer, urb->actual_length);
- #endif
- #if DBG_USB_FIFO
- DBG_I("%s: ep_num: %d urb: %x, actual_length: %d\n",
- __func__, ep_num, urb, urb->actual_length);
- DBG_I("%s: sent: %d, tx_pkt_size: %d\n", __func__, endpoint->sent, endpoint->maxpkt);
- #endif
- count = last = MIN (urb->actual_length - endpoint->sent, endpoint->maxpkt);
- //count = last = urb->actual_length;
- #if DBG_USB_FIFO
- DBG_I("%s: count: %d\n", __func__, count);
- DBG_I("%s: urb->actual_length = %d\n", __func__, urb->actual_length);
- DBG_I("%s: endpoint->sent = %d\n", __func__, endpoint->sent);
- #endif
- if (count < 0) {
- DBG_C("%s: something is wrong, count < 0", __func__);
- }
- if (count) {
- cp = urb->buffer + endpoint->sent;
- #ifdef USB_TX_DMA_MODE_0
- wp = (u32 *)cp;
- arch_clean_invalidate_cache_range((addr_t) cp, count);
- if (ep_num != 0) {
- writel(wp, USB_DMA_ADDR(ep_num));
- writel(count, USB_DMA_COUNT(ep_num));
- dma_cntl =
- USB_DMA_BURST_MODE_3 | (ep_num << USB_DMA_ENDPNT_OFFSET) |
- USB_DMA_EN | USB_DMA_DIR;
- writew(dma_cntl, USB_DMA_CNTL(ep_num));
- while (readw(USB_DMA_CNTL (ep_num)) & USB_DMA_EN);
- } else
- #endif
- {
- //DBG("---------write USB fifo---------\n");
- while (count > 0) {
- //hexdump8(cp, 1);
- writeb(*cp, FIFO (ep_num));
- cp++;
- count--;
- }
- }
- }
- endpoint->last = last;
- endpoint->sent += last;
- writeb(index, INDEX);
- }
- return last;
- }
- static struct udc_endpoint * mt_find_ep(int ep_num, u8 dir) {
- int i;
- u8 in = 0;
- /* convert dir to in */
- if (dir == USB_DIR_IN) /* dir == USB_DIR_IN */
- in = 1;
- /* for (i = 0; i < udc_device->max_endpoints; i++) */
- /* for (i = 0; i < the_gadget->ifc_endpoints; i++) */
- for (i = 0; i < MT_EP_NUM; i++) {
- if ((ep_list[i].num == ep_num) && (ep_list[i].in == in)) {
- #if DBG_USB_GENERAL
- DBG_I("%s: find ep!\n", __func__);
- #endif
- return &ep_list[i];
- }
- }
- return NULL;
- }
- static void mt_udc_flush_fifo(u8 ep_num, u8 dir)
- {
- u16 tmpReg16;
- u8 index;
- struct udc_endpoint *endpoint;
- index = readb(INDEX);
- writeb(ep_num, INDEX);
- if (ep_num == 0) {
- tmpReg16 = readw(IECSR + CSR0);
- tmpReg16 |= EP0_FLUSH_FIFO;
- writew(tmpReg16, IECSR + CSR0);
- writew(tmpReg16, IECSR + CSR0);
- } else {
- endpoint = mt_find_ep(ep_num, dir);
- if (endpoint->in == 0) { /* USB_DIR_OUT */
- tmpReg16 = readw(IECSR + RXCSR);
- tmpReg16 |= EPX_RX_FLUSHFIFO;
- writew(tmpReg16, IECSR + RXCSR);
- writew(tmpReg16, IECSR + RXCSR);
- } else {
- tmpReg16 = readw(IECSR + TXCSR);
- tmpReg16 |= EPX_TX_FLUSHFIFO;
- writew(tmpReg16, IECSR + TXCSR);
- writew(tmpReg16, IECSR + TXCSR);
- }
- }
- /* recover index register */
- writeb(index, INDEX);
- }
- /* the endpoint does not support the received command, stall it!! */
- static void udc_stall_ep(unsigned int ep_num, u8 dir) {
- struct udc_endpoint *endpoint = mt_find_ep(ep_num, dir);
- u8 index;
- u16 csr;
- DBG_C("[USB] %s\n", __func__);
- index = readb(INDEX);
- writeb(ep_num, INDEX);
- if (ep_num == 0) {
- csr = readw(IECSR + CSR0);
- csr |= EP0_SENDSTALL;
- writew(csr, IECSR + CSR0);
- mt_udc_flush_fifo(ep_num, USB_DIR_OUT);
- } else {
- if (endpoint->in == 0) { /* USB_DIR_OUT */
- csr = readb(IECSR + RXCSR);
- csr |= EPX_RX_SENDSTALL;
- writew(csr, IECSR + RXCSR);
- mt_udc_flush_fifo(ep_num, USB_DIR_OUT);
- } else {
- csr = readb(IECSR + TXCSR);
- csr |= EPX_TX_SENDSTALL;
- writew(csr, IECSR + TXCSR);
- mt_udc_flush_fifo(ep_num, USB_DIR_IN);
- }
- }
- //mt_udc_flush_fifo (ep_num, USB_DIR_OUT);
- //mt_udc_flush_fifo (ep_num, USB_DIR_IN);
- ep0_state = EP0_IDLE;
- writeb(index, INDEX);
- return;
- }
- /*
- * If abnormal DATA transfer happened, like USB unplugged,
- * we cannot fix this after mt_udc_reset().
- * Because sometimes there will come reset twice.
- */
- static void mt_udc_suspend(void) {
- /* handle abnormal DATA transfer if we had any */
- struct udc_endpoint *endpoint;
- int i;
- /* deal with flags */
- usb_online = 0;
- usb_config_value = 0;
- the_gadget->notify(the_gadget, UDC_EVENT_OFFLINE);
- /* error out any pending reqs */
- for (i = 1; i < MT_EP_NUM; i++) {
- /* ensure that ept_complete considers
- * this to be an error state
- */
- #if DBG_USB_GENERAL
- DBG_I("%s: ep: %i, in: %s, req: %x\n",
- __func__, ep_list[i].num, ep_list[i].in ? "IN" : "OUT", ep_list[i].req);
- #endif
- if ((ep_list[i].req && (ep_list[i].in == 0)) || /* USB_DIR_OUT */
- (ep_list[i].req && (ep_list[i].in == 1))) { /* USB_DIR_IN */
- ep_list[i].status = -1; /* HALT */
- endpoint = &ep_list[i];
- handle_ept_complete(endpoint);
- }
- }
- }
- static void mt_udc_rxtxmap_recover(void) {
- int i;
- for (i = 1; i < MT_EP_NUM; i++) {
- if (ep_list[i].num != 0) { /* allocated */
- writeb(ep_list[i].num, INDEX);
- if (ep_list[i].in == 0) /* USB_DIR_OUT */
- writel(ep_list[i].maxpkt, (IECSR + RXMAP));
- else
- writel(ep_list[i].maxpkt, (IECSR + TXMAP));
- }
- }
- }
- static void mt_udc_reset(void) {
- /* MUSBHDRC automatically does the following when reset signal is detected */
- /* 1. Sets FAddr to 0
- * 2. Sets Index to 0
- * 3. Flush all endpoint FIFOs
- * 4. Clears all control/status registers
- * 5. Enables all endpoint interrupts
- * 6. Generates a Rest interrupt
- */
- DBG_I("[USB] %s\n", __func__);
- /* disable all endpoint interrupts */
- writeb(0, INTRTXE);
- writeb(0, INTRRXE);
- writeb(0, INTRUSBE);
- writew(SWRST_SWRST | SWRST_DISUSBRESET, SWRST);
- dev_address = 0;
- /* flush FIFO */
- mt_udc_flush_fifo(0, USB_DIR_OUT);
- mt_udc_flush_fifo(1, USB_DIR_OUT);
- mt_udc_flush_fifo(1, USB_DIR_IN);
- //mt_udc_flush_fifo (2, USB_DIR_IN);
- /* detect USB speed */
- if (readb(POWER) & PWR_HS_MODE) {
- DBG_I("[USB] USB High Speed\n");
- // enable_highspeed();
- } else {
- DBG_I("[USB] USB Full Speed\n");
- }
- /* restore RXMAP and TXMAP if the endpoint has been configured */
- mt_udc_rxtxmap_recover();
- /* enable suspend */
- writeb((INTRUSB_SUSPEND | INTRUSB_RESUME | INTRUSB_RESET |INTRUSB_DISCON), INTRUSBE);
- }
- static void mt_udc_ep0_write(void) {
- struct udc_endpoint *endpoint = &ep_list[EP0];
- int count = 0;
- u16 csr0 = 0;
- u8 index = 0;
- index = readb(INDEX);
- writeb(0, INDEX);
- csr0 = readw(IECSR + CSR0);
- if (csr0 & EP0_TXPKTRDY) {
- DBG_I("mt_udc_ep0_write: ep0 is not ready to be written\n");
- return;
- }
- count = mt_write_fifo(endpoint);
- #if DBG_USB_GENERAL
- DBG_I("%s: count = %d\n", __func__, count);
- #endif
- if (count < EP0_MAX_PACKET_SIZE) {
- /* last packet */
- csr0 |= (EP0_TXPKTRDY | EP0_DATAEND);
- ep0_urb->actual_length = 0;
- endpoint->sent = 0;
- ep0_state = EP0_IDLE;
- } else {
- /* more packets are waiting to be transferred */
- csr0 |= EP0_TXPKTRDY;
- }
- writew(csr0, IECSR + CSR0);
- writeb(index, INDEX);
- return;
- }
- static void mt_udc_ep0_read(void) {
- struct udc_endpoint *endpoint = &ep_list[EP0];
- int count = 0;
- u16 csr0 = 0;
- u8 index = 0;
- index = readb(INDEX);
- writeb(EP0, INDEX);
- csr0 = readw(IECSR + CSR0);
- /* erroneous ep0 interrupt */
- if (!(csr0 & EP0_RXPKTRDY)) {
- return;
- }
- count = mt_read_fifo(endpoint);
- if (count <= EP0_MAX_PACKET_SIZE) {
- /* last packet */
- csr0 |= (EP0_SERVICED_RXPKTRDY | EP0_DATAEND);
- ep0_state = EP0_IDLE;
- } else {
- /* more packets are waiting to be transferred */
- csr0 |= EP0_SERVICED_RXPKTRDY;
- }
- writew(csr0, IECSR + CSR0);
- writeb(index, INDEX);
- return;
- }
- static int ep0_standard_setup(struct urb *urb) {
- struct setup_packet *request;
- struct udc_descriptor *desc;
- //struct udc_device *device;
- u8 *cp = urb->buffer;
- #if 0
- if (!urb || !urb->device) {
- DBG ("\n!urb || !urb->device\n");
- return FALSE;
- }
- #endif
- request = &urb->device_request;
- //device = urb->device;
- dump_setup_packet("[USB] Device Request\n", request);
- if ((request->type & USB_TYPE_MASK) != 0) {
- return FALSE; /* Class-specific requests are handled elsewhere */
- }
- /* handle all requests that return data (direction bit set on bm RequestType) */
- if ((request->type & USB_EP_DIR_MASK)) {
- /* send the descriptor */
- ep0_state = EP0_TX;
- switch (request->request) {
- /* data stage: from device to host */
- case GET_STATUS:
- #if DBG_USB_GENERAL
- DBG_I("GET_STATUS\n");
- #endif
- urb->actual_length = 2;
- cp[0] = cp[1] = 0;
- switch (request->type & USB_RECIP_MASK) {
- case USB_RECIP_DEVICE:
- cp[0] = USB_STAT_SELFPOWERED;
- break;
- case USB_RECIP_OTHER:
- urb->actual_length = 0;
- break;
- default:
- break;
- }
- return 0;
- case GET_DESCRIPTOR:
- #if DBG_USB_GENERAL
- DBG_I("GET_DESCRIPTOR\n");
- #endif
- /* usb_highspeed? */
- for (desc = desc_list; desc; desc = desc->next) {
- #if DBG_USB_DUMP_DESC
- DBG_I("desc->tag: %x: request->value: %x\n", desc->tag, request->value);
- #endif
- if (desc->tag == request->value) {
- #if DBG_USB_DUMP_DESC
- DBG_I("Find packet!\n");
- #endif
- unsigned len = desc->len;
- if (len > request->length)
- len = request->length;
- #if DBG_USB_GENERAL
- DBG_I("%s: urb: %x, cp: %p\n", __func__, urb, cp);
- #endif
- copy_desc(urb, desc->data, len);
- return 0;
- }
- }
- /* descriptor lookup failed */
- return FALSE;
- case GET_CONFIGURATION:
- #if DBG_USB_GENERAL
- DBG_I("GET_CONFIGURATION\n");
- DBG_I("USB_EP_DIR_MASK\n");
- #endif
- #if 0
- urb->actual_length = 1;
- ((char *) urb->buffer)[0] = device->configuration;
- #endif
- // return 0;
- break;
- case GET_INTERFACE:
- #if DBG_USB_GENERAL
- DBG_I("GET_INTERFACE\n");
- #endif
- #if 0
- urb->actual_length = 1;
- ((char *) urb->buffer)[0] = device->alternate;
- return 0;
- #endif
- default:
- DBG_C("Unsupported command with TX data stage\n");
- break;
- }
- } else {
- switch (request->request) {
- case SET_ADDRESS:
- #if DBG_USB_GENERAL
- DBG_I("SET_ADDRESS\n");
- #endif
- dev_address = (request->value);
- set_address = 1;
- return 0;
- case SET_CONFIGURATION:
- #if DBG_USB_GENERAL
- DBG_I("SET_CONFIGURATION\n");
- #endif
- #if 0
- device->configuration = (request->value) & 0x7f;
- device->interface = device->alternate = 0;
- #endif
- if (request->value == 1) {
- usb_config_value = 1;
- the_gadget->notify(the_gadget, UDC_EVENT_ONLINE);
- } else {
- usb_config_value = 0;
- the_gadget->notify(the_gadget, UDC_EVENT_OFFLINE);
- }
- usb_online = request->value ? 1 : 0;
- //usb_status(request->value ? 1 : 0, usb_highspeed);
- return 0;
- default:
- DBG_C("Unsupported command with RX data stage\n");
- break;
- }
- }
- return FALSE;
- }
- static void mt_udc_ep0_setup(void) {
- struct udc_endpoint *endpoint = &ep_list[0];
- u8 index;
- u8 stall = 0;
- u16 csr0;
- struct setup_packet *request;
- #ifdef USB_DEBUG
- u16 count;
- #endif
- index = readb(INDEX);
- writeb(0, INDEX);
- /* Read control status register for endpiont 0 */
- csr0 = readw(IECSR + CSR0);
- /* check whether RxPktRdy is set? */
- if (!(csr0 & EP0_RXPKTRDY))
- return;
- /* unload fifo */
- ep0_urb->actual_length = 0;
- #ifndef USB_DEBUG
- mt_read_fifo(endpoint);
- #else
- count = mt_read_fifo(endpoint);
- #if DBG_USB_FIFO
- DBG_I("%s: mt_read_fifo count = %d\n", __func__, count);
- #endif
- #endif
- /* decode command */
- request = &ep0_urb->device_request;
- memcpy(request, ep0_urb->buffer, sizeof(struct setup_packet));
- if (((request->type) & USB_TYPE_MASK) == USB_TYPE_STANDARD) {
- #if DBG_USB_GENERAL
- DBG_I("[USB] Standard Request\n");
- #endif
- stall = ep0_standard_setup(ep0_urb);
- if (stall) {
- dump_setup_packet("[USB] STANDARD REQUEST NOT SUPPORTED\n", request);
- }
- } else if (((request->type) & USB_TYPE_MASK) == USB_TYPE_CLASS) {
- #if DBG_USB_GENERAL
- DBG_I("[USB] Class-Specific Request\n");
- #endif
- // stall = ep0_class_setup(ep0_urb);
- if (stall) {
- dump_setup_packet("[USB] CLASS REQUEST NOT SUPPORTED\n", request);
- }
- } else if (((request->type) & USB_TYPE_MASK) == USB_TYPE_VENDOR) {
- #if DBG_USB_GENERAL
- DBG_I("[USB] Vendor-Specific Request\n");
- /* do nothing now */
- DBG_I("[USB] ALL VENDOR-SPECIFIC REQUESTS ARE NOT SUPPORTED!!\n");
- #endif
- }
- if (stall) {
- /* the received command is not supported */
- udc_stall_ep(0, USB_DIR_OUT);
- return;
- }
- switch (ep0_state) {
- case EP0_TX:
- /* data stage: from device to host */
- #if DBG_USB_GENERAL
- DBG_I("%s: EP0_TX\n", __func__);
- #endif
- csr0 = readw(IECSR + CSR0);
- csr0 |= (EP0_SERVICED_RXPKTRDY);
- writew(csr0, IECSR + CSR0);
- mt_udc_ep0_write();
- break;
- case EP0_RX:
- /* data stage: from host to device */
- #if DBG_USB_GENERAL
- DBG_I("%s: EP0_RX\n", __func__);
- #endif
- csr0 = readw(IECSR + CSR0);
- csr0 |= (EP0_SERVICED_RXPKTRDY);
- writew(csr0, IECSR + CSR0);
- break;
- case EP0_IDLE:
- /* no data stage */
- #if DBG_USB_GENERAL
- DBG_I("%s: EP0_IDLE\n", __func__);
- #endif
- csr0 = readw(IECSR + CSR0);
- csr0 |= (EP0_SERVICED_RXPKTRDY | EP0_DATAEND);
- writew(csr0, IECSR + CSR0);
- writew(csr0, IECSR + CSR0);
- break;
- default:
- break;
- }
- writeb(index, INDEX);
- return;
- }
- static void mt_udc_ep0_handler(void) {
- u16 csr0;
- u8 index = 0;
- index = readb(INDEX);
- writeb(0, INDEX);
- csr0 = readw(IECSR + CSR0);
- if (csr0 & EP0_SENTSTALL) {
- #if DBG_USB_GENERAL
- DBG_I("USB: [EP0] SENTSTALL\n");
- #endif
- /* needs implementation for exception handling here */
- ep0_state = EP0_IDLE;
- }
- if (csr0 & EP0_SETUPEND) {
- #if DBG_USB_GENERAL
- DBG_I("USB: [EP0] SETUPEND\n");
- #endif
- csr0 |= EP0_SERVICE_SETUP_END;
- writew(csr0, IECSR + CSR0);
- ep0_state = EP0_IDLE;
- }
- switch (ep0_state) {
- case EP0_IDLE:
- #if DBG_USB_GENERAL
- DBG_I("%s: EP0_IDLE\n", __func__);
- #endif
- if (set_address) {
- writeb(dev_address, FADDR);
- set_address = 0;
- }
- mt_udc_ep0_setup();
- break;
- case EP0_TX:
- #if DBG_USB_GENERAL
- DBG_I("%s: EP0_TX\n", __func__);
- #endif
- mt_udc_ep0_write();
- break;
- case EP0_RX:
- #if DBG_USB_GENERAL
- DBG_I("%s: EP0_RX\n", __func__);
- #endif
- mt_udc_ep0_read();
- break;
- default:
- break;
- }
- writeb(index, INDEX);
- return;
- }
- /*
- * udc_setup_ep - setup endpoint
- *
- * Associate a physical endpoint with endpoint_instance and initialize FIFO
- */
- void mt_setup_ep(unsigned int ep, struct udc_endpoint *endpoint) {
- u8 index;
- u16 csr;
- u16 csr0;
- u16 max_packet_size;
- u8 fifosz = 0;
- /* EP table records in bits hence bit 1 is ep0 */
- index = readb(INDEX);
- writeb(ep, INDEX);
- if (ep == EP0) {
- /* Read control status register for endpiont 0 */
- csr0 = readw(IECSR + CSR0);
- /* check whether RxPktRdy is set? */
- if (!(csr0 & EP0_RXPKTRDY))
- return;
- }
- /* Configure endpoint fifo */
- /* Set fifo address, fifo size, and fifo max packet size */
- #if DBG_USB_GENERAL
- DBG_I("%s: endpoint->in: %d, maxpkt: %d\n",
- __func__, endpoint->in, endpoint->maxpkt);
- #endif
- if (endpoint->in == 0) { /* USB_DIR_OUT */
- /* Clear data toggle to 0 */
- csr = readw(IECSR + RXCSR);
- /* pangyen 20090911 */
- csr |= EPX_RX_CLRDATATOG | EPX_RX_FLUSHFIFO;
- writew(csr, IECSR + RXCSR);
- /* Set fifo address */
- writew(fifo_addr >> 3, RXFIFOADD);
- /* Set fifo max packet size */
- max_packet_size = endpoint->maxpkt;
- writew(max_packet_size, IECSR + RXMAP);
- /* Set fifo size (double buffering is currently not enabled) */
- switch (max_packet_size) {
- case 8:
- case 16:
- case 32:
- case 64:
- case 128:
- case 256:
- case 512:
- case 1024:
- case 2048:
- if (endpoint->mode == DOUBLE_BUF)
- fifosz |= FIFOSZ_DPB;
- case 4096:
- fifosz |= uffs(max_packet_size >> 4);
- writeb(fifosz, RXFIFOSZ);
- break;
- case 3072:
- fifosz = uffs(4096 >> 4);
- writeb(fifosz, RXFIFOSZ);
- break;
- default:
- DBG_C("The max_packet_size for ep %d is not supported\n", ep);
- }
- } else {
- /* Clear data toggle to 0 */
- csr = readw(IECSR + TXCSR);
- /* pangyen 20090911 */
- csr |= EPX_TX_CLRDATATOG | EPX_TX_FLUSHFIFO;
- writew(csr, IECSR + TXCSR);
- /* Set fifo address */
- writew(fifo_addr >> 3, TXFIFOADD);
- /* Set fifo max packet size */
- max_packet_size = endpoint->maxpkt;
- writew(max_packet_size, IECSR + TXMAP);
- /* Set fifo size(double buffering is currently not enabled) */
- switch (max_packet_size) {
- case 8:
- case 16:
- case 32:
- case 64:
- case 128:
- case 256:
- case 512:
- case 1024:
- case 2048:
- if (endpoint->mode == DOUBLE_BUF)
- fifosz |= FIFOSZ_DPB;
- case 4096:
- fifosz |= uffs(max_packet_size >> 4);
- writeb(fifosz, TXFIFOSZ);
- break;
- case 3072:
- fifosz = uffs(4096 >> 4);
- writeb(fifosz, TXFIFOSZ);
- break;
- default:
- DBG_C("The max_packet_size for ep %d is not supported\n", ep);
- }
- }
- if (endpoint->mode == DOUBLE_BUF)
- fifo_addr += (max_packet_size << 1);
- else
- fifo_addr += max_packet_size;
- /* recover INDEX register */
- writeb(index, INDEX);
- }
- struct udc_endpoint *_udc_endpoint_alloc(unsigned char num, unsigned char in,
- unsigned short max_pkt) {
- int i;
- /*
- * find an unused slot in ep_list from EP1 to MAX_EP
- * for example, EP1 will use 2 slot one for IN and the other for OUT
- */
- if (num != EP0) {
- for (i = 1; i < MT_EP_NUM; i++) {
- if (ep_list[i].num == 0) /* usable */
- break;
- }
- if (i == MT_EP_NUM) /* ep has been exhausted. */
- return NULL;
- if (in) { /* usb EP1 tx */
- ep_list[i].tx_urb = tx_urb;
- #ifdef USB_DOUBLE_BUF
- ep_list[i].mode = DOUBLE_BUF;
- #endif
- } else { /* usb EP1 rx */
- ep_list[i].rcv_urb = rx_urb;
- #ifdef USB_DOUBLE_BUF
- ep_list[i].mode = DOUBLE_BUF;
- #endif
- }
- } else {
- i = EP0; /* EP0 */
- }
- ep_list[i].maxpkt = max_pkt;
- ep_list[i].num = num;
- ep_list[i].in = in;
- ep_list[i].req = NULL;
- /* store EPT_TX/RX info */
- if (ep_list[i].in) {
- ep_list[i].bit = EPT_TX(num);
- } else {
- ep_list[i].bit = EPT_RX(num);
- }
- /* write parameters to this ep (write to hardware) */
- mt_setup_ep(num, &ep_list[i]);
- DBG_I("[USB] ept%d %s @%p/%p max=%d bit=%x\n",
- num, in ? "in" : "out", &ep_list[i], &ep_list, max_pkt, ep_list[i].bit);
- return &ep_list[i];
- }
- #define SETUP(type,request) (((type) << 8) | (request))
- static unsigned long ept_alloc_table = EPT_TX(0) | EPT_RX(0);
- struct udc_endpoint *udc_endpoint_alloc(unsigned type, unsigned maxpkt)
- {
- struct udc_endpoint *ept;
- unsigned n;
- unsigned in;
- if (type == UDC_TYPE_BULK_IN) {
- in = 1;
- } else if (type == UDC_TYPE_BULK_OUT) {
- in = 0;
- } else {
- return 0;
- }
- /* udc_endpoint_alloc is used for EPx except EP0 */
- for (n = 1; n < 16; n++) {
- unsigned long bit = in ? EPT_TX(n) : EPT_RX(n);
- if (ept_alloc_table & bit)
- continue;
- ept = _udc_endpoint_alloc(n, in, maxpkt);
- if (ept)
- ept_alloc_table |= bit;
- return ept;
- }
- return 0;
- }
- static void handle_ept_complete(struct udc_endpoint *ept)
- {
- unsigned int actual;
- int status;
- struct udc_request *req;
- req = ept->req;
- if (req) {
- #if DBG_USB_GENERAL
- DBG_I("%s: req: %x: req->length: %d: status: %d\n", __func__, req, req->length, ept->status);
- #endif
- /* release this request for processing next */
- ept->req = NULL;
- if (ept->status == -1) {
- actual = 0;
- status = -1;
- DBG_C("%s: EP%d/%s FAIL status: %x\n",
- __func__, ept->num, ept->in ? "in" : "out", status);
- } else {
- actual = req->length;
- status = 0;
- }
- if (req->complete)
- req->complete(req, actual, status);
- }
- }
- static void mt_udc_epx_handler(u8 ep_num, u8 dir)
- {
- u8 index;
- u16 csr;
- u32 count;
- struct udc_endpoint *endpoint;
- struct urb *urb;
- struct udc_request *req; /* for event signaling */
- u8 intrrxe;
- endpoint = mt_find_ep(ep_num, dir);
- index = readb(INDEX);
- writeb(ep_num, INDEX);
- #if DBG_USB_GENERAL
- DBG_I("EP%d Interrupt\n", ep_num);
- DBG_I("dir: %x\n", dir);
- #endif
- switch (dir) {
- case USB_DIR_OUT:
- /* transfer direction is from host to device */
- /* from the view of usb device, it's RX */
- csr = readw(IECSR + RXCSR);
- if (csr & EPX_RX_SENTSTALL) {
- DBG_C("EP %d(RX): STALL\n", ep_num);
- /* exception handling: implement this!! */
- return;
- }
- if (!(csr & EPX_RX_RXPKTRDY)) {
- #if DBG_USB_GENERAL
- DBG_I("EP %d: ERRONEOUS INTERRUPT\n", ep_num); // normal
- #endif
- return;
- }
- //DBG_C("mt_read_fifo, start\n");
- count = mt_read_fifo(endpoint);
- //DBG_C("mt_read_fifo, end\n");
- #if DBG_USB_GENERAL
- DBG_I("EP%d(RX), count = %d\n", ep_num, count);
- #endif
- csr &= ~EPX_RX_RXPKTRDY;
- writew(csr, IECSR + RXCSR);
- if (readw(IECSR + RXCSR) & EPX_RX_RXPKTRDY) {
- #if DBG_USB_GENERAL
- DBG_I("%s: rxpktrdy clear failed\n", __func__);
- #endif
- }
- /* do signaling */
- req = endpoint->req;
- /* workaround: if req->lenth == 64 bytes (not huge data transmission)
- * do normal return */
- #if DBG_USB_GENERAL
- DBG_I("%s: req->length: %x, endpoint->rcv_urb->actual_length: %x\n",
- __func__, req->length, endpoint->rcv_urb->actual_length);
- #endif
- /* Deal with FASTBOOT command */
- if ((req->length >= endpoint->rcv_urb->actual_length) && req->length == 64) {
- req->length = count;
- /* mask EPx INTRRXE */
- /* The buffer is passed from the AP caller.
- * It happens that AP is dealing with the buffer filled data by driver,
- * but the driver is still receiving the next data packets onto the buffer.
- * Data corrupted happens if the every request use the same buffer.
- * Mask the EPx to ensure that AP and driver are not accessing the buffer parallely.
- */
- intrrxe = readb(INTRRXE);
- writeb((intrrxe &= ~(1 << ep_num)), INTRRXE);
- }
- /* Deal with DATA transfer */
- if ((req->length == endpoint->rcv_urb->actual_length) ||
- ((req->length >= endpoint->rcv_urb->actual_length) && req->length == 64)) {
- handle_ept_complete(endpoint);
- /* mask EPx INTRRXE */
- /* The buffer is passed from the AP caller.
- * It happens that AP is dealing with the buffer filled data by driver,
- * but the driver is still receiving the next data packets onto the buffer.
- * Data corrupted happens if the every request use the same buffer.
- * Mask the EPx to ensure that AP and driver are not accessing the buffer parallely.
- */
- intrrxe = readb(INTRRXE);
- writeb((intrrxe &= ~(1 << ep_num)), INTRRXE);
- }
- break;
- case USB_DIR_IN:
- /* transfer direction is from device to host */
- /* from the view of usb device, it's tx */
- csr = readw(IECSR + TXCSR);
- if (csr & EPX_TX_SENTSTALL) {
- DBG_C("EP %d(TX): STALL\n", ep_num);
- endpoint->status = -1;
- handle_ept_complete(endpoint);
- /* exception handling: implement this!! */
- return;
- }
- if (csr & EPX_TX_TXPKTRDY) {
- DBG_C
- ("mt_udc_epx_handler: ep%d is not ready to be written\n",
- ep_num);
- return;
- }
- urb = endpoint->tx_urb;
- if (endpoint->sent == urb->actual_length) {
- /* do signaling */
- handle_ept_complete(endpoint);
- break;
- }
- /* send next packet of the same urb */
- count = mt_write_fifo(endpoint);
- #if DBG_USB_GENERAL
- DBG_I("EP%d(TX), count = %d\n", ep_num, endpoint->sent);
- #endif
- if (count != 0) {
- /* not the interrupt generated by the last tx packet of the transfer */
- csr |= EPX_TX_TXPKTRDY;
- writew(csr, IECSR + TXCSR);
- }
- break;
- default:
- break;
- }
- writeb(index, INDEX);
- return;
- }
- void mt_udc_irq(u8 intrtx, u8 intrrx, u8 intrusb) {
- int i;
- DBG_IRQ("[USB] INTERRUPT\n");
- if (intrusb) {
- if (intrusb & INTRUSB_RESUME) {
- DBG_IRQ("[USB] INTRUSB: RESUME\n");
- }
- if (intrusb & INTRUSB_SESS_REQ) {
- DBG_IRQ("[USB] INTRUSB: SESSION REQUEST\n");
- }
- if (intrusb & INTRUSB_VBUS_ERROR) {
- DBG_IRQ("[USB] INTRUSB: VBUS ERROR\n");
- }
- if (intrusb & INTRUSB_SUSPEND) {
- DBG_IRQ("[USB] INTRUSB: SUSPEND\n");
- mt_udc_suspend();
- }
- if (intrusb & INTRUSB_CONN) {
- DBG_IRQ("[USB] INTRUSB: CONNECT\n");
- }
- if (intrusb & INTRUSB_DISCON) {
- DBG_IRQ("[USB] INTRUSB: DISCONNECT\n");
- }
- if (intrusb & INTRUSB_RESET) {
- DBG_IRQ("[USB] INTRUSB: RESET\n");
- mt_udc_reset();
- }
- if (intrusb & INTRUSB_SOF) {
- DBG_IRQ("[USB] INTRUSB: SOF\n");
- }
- }
- /* endpoint 0 interrupt? */
- if (intrtx & EPMASK (0)) {
- mt_udc_ep0_handler();
- intrtx &= ~0x1;
- }
- if (intrtx) {
- for (i = 1; i < MT_EP_NUM; i++) {
- if (intrtx & EPMASK (i)) {
- mt_udc_epx_handler(i, USB_DIR_IN);
- }
- }
- }
- if (intrrx) {
- for (i = 1; i < MT_EP_NUM; i++) {
- if (intrrx & EPMASK (i)) {
- mt_udc_epx_handler(i, USB_DIR_OUT);
- }
- }
- }
- }
- void service_interrupts(void)
- {
- volatile u8 intrtx, intrrx, intrusb;
- /* polling interrupt status for incoming interrupts and service it */
- intrtx = readb(INTRTX) & readb(INTRTXE);
- intrrx = readb(INTRRX) & readb(INTRRXE);
- intrusb = readb(INTRUSB) & readb(INTRUSBE);
- writeb(intrtx, INTRTX);
- writeb(intrrx, INTRRX);
- writeb(intrusb, INTRUSB);
- intrusb &= ~INTRUSB_SOF;
- if (intrtx | intrrx | intrusb) {
- mt_udc_irq(intrtx, intrrx, intrusb);
- }
- }
- void lk_usb_scheduler(void)
- {
- mt_irq_ack(MT_USB0_IRQ_ID);
- service_interrupts();
- #if 0
- static enum handler_return ret;
- ret = INT_RESCHEDULE;
- if (ret == INT_RESCHEDULE) {
- thread_preempt();
- }
- #endif
- return;
- }
- int mt_usb_irq_init(void) {
- /* disable all endpoint interrupts */
- writeb(0, INTRTXE);
- writeb(0, INTRRXE);
- writeb(0, INTRUSBE);
- /* 2. Ack all gpt irq if needed */
- //writel(0x3F, GPT_IRQ_ACK);
- /* 3. Register usb irq */
- mt_irq_set_sens(MT_USB0_IRQ_ID, MT65xx_LEVEL_SENSITIVE);
- mt_irq_set_polarity(MT_USB0_IRQ_ID, MT65xx_POLARITY_LOW);
- return 0;
- }
- /* Turn on the USB connection by enabling the pullup resistor */
- void mt_usb_connect_internal(void)
- {
- u8 tmpReg8;
- /* connect */
- tmpReg8 = readb(POWER);
- tmpReg8 |= PWR_SOFT_CONN;
- tmpReg8 |= PWR_ENABLE_SUSPENDM;
- #ifdef USB_FORCE_FULL_SPEED
- tmpReg8 &= ~PWR_HS_ENAB;
- #else
- tmpReg8 |= PWR_HS_ENAB;
- #endif
- writeb(tmpReg8, POWER);
- }
- /* Turn off the USB connection by disabling the pullup resistor */
- void mt_usb_disconnect_internal(void)
- {
- u8 tmpReg8;
- /* connect */
- tmpReg8 = readb(POWER);
- tmpReg8 &= ~PWR_SOFT_CONN;
- writeb(tmpReg8, POWER);
- }
- int udc_init(struct udc_device *dev)
- {
- struct udc_descriptor *desc = NULL;
- #ifdef USB_GINTR
- #ifdef USB_HSDMA_ISR
- u32 usb_dmaintr;
- #endif
- u32 usb_l1intm;
- #endif
- DBG_I("[USB] %s:\n", __func__);
- DBG_I("[USB] ep0_urb: %p\n", ep0_urb);
- /* RESET */
- /*
- * mt_usb_disconnect_internal can be removed:
- * if we call udc_stop() in cmd_reboot and cmd_reboot_bootloader.
- */
- //mt_usb_disconnect_internal();
- thread_sleep(20);
- #if 0 /* Wait for HW designer's instruction (depends on tapeout process) */
- //#if !CFG_FPGA_PLATFORM
- //ALPS00427972, implement the analog register formula
- //Set the calibration after power on
- //Add here for eFuse, chip version checking -> analog register calibration
- int input_reg = INREG16(M_HW_RES3);
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: input_reg = 0x%x \n", __func__, input_reg);
- #endif
- int term_vref = (input_reg & RG_USB20_TERM_VREF_SEL_MASK) >> 13; //0xE000 //0b 1110,0000,0000,0000 15~13
- int clkref = (input_reg & RG_USB20_CLKREF_REF_MASK) >> 10; //0x1C00 //0b 0001,1100,0000,0000 12~10
- int vrt_vref = (input_reg & RG_USB20_VRT_VREF_SEL_MASK) >> 7; //0x0380 //0b 0000,0011,1000,0000 9~7
- #if DBG_PHY_CALIBRATION
- DBG_I("%s: term_vref = 0x%x, clkref = 0x%x, vrt_vref = 0x%x,\n", __func__, term_vref, clkref, vrt_vref);
- #endif
- if (term_vref)
- mt_usb_phy_calibraion(1, term_vref);
- if (clkref)
- mt_usb_phy_calibraion(2, clkref);
- if (vrt_vref)
- mt_usb_phy_calibraion(3, vrt_vref);
- //ALPS00427972, implement the analog register formula
- //#endif
- #endif
- #if 0
- if (get_devinfo_with_index(14) & (0x01<<22))
- {
- USBPHY_CLR8(0x00, 0x20);
- }
- if (get_devinfo_with_index(14) & (0x07<<19))
- {
- //RG_USB20_VRT_VREF_SEL[2:0]=5 (ori:4) (0x11110804[14:12])
- USBPHY_CLR8(0x05, 0x70);
- USBPHY_SET8(0x05, ((get_devinfo_with_index(7)>>19)<<4) & (0x70));
- }
- #endif
- /* usb phy init */
- board_usb_init();
- mt_usb_phy_recover();
- thread_sleep(20);
- /* allocate ep0 */
- ep0out = _udc_endpoint_alloc(EP0, 0, EP0_MAX_PACKET_SIZE);
- ep0in = _udc_endpoint_alloc(EP0, 1, EP0_MAX_PACKET_SIZE);
- ep0req = udc_request_alloc();
- ep0req->buf = malloc(4096);
- ep0_urb->buffer = ep0_buf;
- {
- /* create and register a language table descriptor */
- /* language 0x0409 is US English */
- desc = udc_descriptor_alloc(TYPE_STRING, EP0, 4);
- desc->data[2] = 0x09;
- desc->data[3] = 0x04;
- udc_descriptor_register(desc);
- }
- #ifdef USB_HSDMA_ISR
- /* setting HSDMA interrupt register */
- usb_dmaintr = (0xff | 0xff << USB_DMA_INTR_UNMASK_SET_OFFSET);
- writel(usb_dmaintr, USB_DMA_INTR);
- #endif
- #ifdef USB_GINTR
- usb_l1intm = (TX_INT_STATUS | RX_INT_STATUS | USBCOM_INT_STATUS | DMA_INT_STATUS);
- writel(usb_l1intm, USB_L1INTM);
- #endif
- the_device = dev;
- return 0;
- }
- void udc_endpoint_free(struct udc_endpoint *ept)
- {
- /* todo */
- }
- struct udc_request *udc_request_alloc(void)
- {
- struct udc_request *req;
- req = malloc(sizeof(*req));
- req->buf = NULL;
- req->length = 0;
- return req;
- }
- void udc_request_free(struct udc_request *req)
- {
- free(req);
- }
- /* Called to start packet transmission. */
- /* It must be applied in udc_request_queue when polling mode is used.
- * (When USB_GINTR is undefined).
- * If interrupt mode is used, you can use
- * mt_udc_epx_handler(ept->num, USB_DIR_IN); to replace mt_ep_write make ISR
- * do it for you.
- */
- static int mt_ep_write(struct udc_endpoint *endpoint)
- {
- int ep_num = endpoint->num;
- int count;
- u8 index;
- u16 csr;
- index = readb(INDEX);
- writeb(ep_num, INDEX);
- /* udc_endpoint_write: cannot write ep0 */
- if (ep_num == 0)
- return FALSE;
- /* udc_endpoint_write: cannot write USB_DIR_OUT */
- if (endpoint->in == 0)
- return FALSE;
- csr = readw(IECSR + TXCSR);
- if (csr & EPX_TX_TXPKTRDY) {
- #if DBG_USB_GENERAL
- DBG_I("[USB]: udc_endpoint_write: ep%d is not ready to be written\n",
- ep_num);
- #endif
- return FALSE;
- }
- count = mt_write_fifo(endpoint);
- csr |= EPX_TX_TXPKTRDY;
- writew(csr, IECSR + TXCSR);
- writeb(index, INDEX);
- return count;
- }
- int udc_request_queue(struct udc_endpoint *ept, struct udc_request *req) {
- u8 intrrxe;
- #if DBG_USB_GENERAL
- DBG_I("[USB] %s: ept%d %s queue req=%p, req->length=%x\n",
- __func__, ept->num, ept->in ? "in" : "out", req, req->length);
- DBG_I("[USB] %s: ept%d: %x, ept->in: %s, ept->rcv_urb->buffer: %x, req->buf: %x\n",
- __func__, ept->num, ept, ept->in ? "IN" : "OUT" , ept->rcv_urb->buffer, req->buf);
- #endif
- enter_critical_section();
- ept->req = req;
- ept->status = 0; /* ACTIVE */
- ept->sent = 0;
- ept->last = 0;
- /* read */
- if (!ept->in) {
- ept->rcv_urb->buffer = req->buf;
- ept->rcv_urb->actual_length = 0;
- /* unmask EPx INTRRXE */
- /*
- * To avoid the parallely access the buffer,
- * it is umasked here and umask at complete.
- */
- intrrxe = readb(INTRRXE);
- intrrxe |= (1 << ept->num);
- writeb(intrrxe, INTRRXE);
- }
- /* write */
- if (ept->in) {
- ept->tx_urb->buffer = req->buf;
- ept->tx_urb->actual_length = req->length;
- mt_ep_write(ept);
- }
- exit_critical_section();
- return 0;
- }
- #if 0
- enum handler_return udc_interrupt(void *arg)
- {
- struct udc_endpoint *ept;
- unsigned ret;
- return ret;
- }
- #endif
- int udc_register_gadget(struct udc_gadget *gadget)
- {
- if (the_gadget) {
- DBG_C("only one gadget supported\n");
- return FALSE;
- }
- the_gadget = gadget;
- return 0;
- }
- static void udc_ept_desc_fill(struct udc_endpoint *ept, unsigned char *data)
- {
- data[0] = 7;
- data[1] = TYPE_ENDPOINT;
- data[2] = ept->num | (ept->in ? USB_DIR_IN : USB_DIR_OUT);
- data[3] = 0x02; /* bulk -- the only kind we support */
- data[4] = ept->maxpkt;
- data[5] = ept->maxpkt >> 8;
- data[6] = ept->in ? 0x00 : 0x01;
- }
- static unsigned udc_ifc_desc_size(struct udc_gadget *g)
- {
- return 9 + g->ifc_endpoints * 7;
- }
- static void udc_ifc_desc_fill(struct udc_gadget *g, unsigned char *data)
- {
- unsigned n;
- data[0] = 0x09;
- data[1] = TYPE_INTERFACE;
- data[2] = 0x00; /* ifc number */
- data[3] = 0x00; /* alt number */
- data[4] = g->ifc_endpoints;
- data[5] = g->ifc_class;
- data[6] = g->ifc_subclass;
- data[7] = g->ifc_protocol;
- data[8] = udc_string_desc_alloc(g->ifc_string);
- data += 9;
- for (n = 0; n < g->ifc_endpoints; n++) {
- udc_ept_desc_fill(g->ept[n], data);
- data += 7;
- }
- }
- int udc_start(void)
- {
- struct udc_descriptor *desc;
- unsigned char *data;
- unsigned size;
- DBG_C("[USB] %s\n", __func__);
- if (!the_device) {
- DBG_C("udc cannot start before init\n");
- return FALSE;
- }
- if (!the_gadget) {
- DBG_C("udc has no gadget registered\n");
- return FALSE;
- }
- /* create our device descriptor */
- desc = udc_descriptor_alloc(TYPE_DEVICE, EP0, 18);
- data = desc->data;
- data[2] = 0x00; /* usb spec minor rev */
- data[3] = 0x02; /* usb spec major rev */
- data[4] = 0x00; /* class */
- data[5] = 0x00; /* subclass */
- data[6] = 0x00; /* protocol */
- data[7] = 0x40; /* max packet size on ept 0 */
- memcpy(data + 8, &the_device->vendor_id, sizeof(short));
- memcpy(data + 10, &the_device->product_id, sizeof(short));
- memcpy(data + 12, &the_device->version_id, sizeof(short));
- data[14] = udc_string_desc_alloc(the_device->manufacturer);
- data[15] = udc_string_desc_alloc(the_device->product);
- data[16] = udc_string_desc_alloc(the_device->serialno);
- data[17] = 1; /* number of configurations */
- udc_descriptor_register(desc);
- /* create our configuration descriptor */
- size = 9 + udc_ifc_desc_size(the_gadget);
- desc = udc_descriptor_alloc(TYPE_CONFIGURATION, EP0, size);
- data = desc->data;
- data[0] = 0x09;
- data[2] = size;
- data[3] = size >> 8;
- data[4] = 0x01; /* number of interfaces */
- data[5] = 0x01; /* configuration value */
- data[6] = 0x00; /* configuration string */
- data[7] = 0x80; /* attributes */
- data[8] = 0x80; /* max power (250ma) -- todo fix this */
- udc_ifc_desc_fill(the_gadget, data + 9);
- udc_descriptor_register(desc);
- #if DBG_USB_DUMP_DESC
- DBG_I("%s: dump desc_list\n", __func__);
- for (desc = desc_list; desc; desc = desc->next) {
- DBG_I("tag: %04x\n", desc->tag);
- DBG_I("len: %d\n", desc->len);
- DBG_I("data:");
- hexdump8(desc->data, desc->len);
- }
- #endif
- /* register interrupt handler */
- mt_usb_irq_init();
- /* go to RUN mode */
- mt_usb_phy_recover();
- /* clear INTRTX, INTRRX and INTRUSB */
- writew(0xffff, INTRTX); /* writew */
- writew(0xffff, INTRRX); /* writew */
- writeb(0xff, INTRUSB); /* writeb */
- /* unmask usb irq */
- #ifdef USB_GINTR
- mt_irq_unmask(MT_USB0_IRQ_ID);
- #endif
- writeb((INTRUSB_SUSPEND | INTRUSB_RESUME | INTRUSB_RESET |INTRUSB_DISCON), INTRUSBE);
- /* enable the pullup resistor */
- mt_usb_connect_internal();
- while (1) {
- #ifdef USB_GINTR
- thread_sleep(1);
- #else
- service_interrupts();
- #endif
- }
- return 0;
- }
- int udc_stop(void)
- {
- thread_sleep(10);
- mt_usb_disconnect_internal();
- mt_usb_phy_savecurrent();
- return 0;
- }
|