alif/tinyusb_port: Add Alif TinyUSB DCD driver.
From https://github.com/alifsemi/alif_vscode-tinyusb.git, commit c79f39361d334ee44f44fed30c56e70dbb368649 Signed-off-by: Damien George <damien.p.george@gmail.com> Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
This commit is contained in:
691
ports/alif/tinyusb_port/alif_dcd_reg.h
Normal file
691
ports/alif/tinyusb_port/alif_dcd_reg.h
Normal file
@@ -0,0 +1,691 @@
|
||||
// *FORMAT-OFF*
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
/// @file alif_dcd_reg.h
|
||||
/// @author karol.saja@alifsemi.com
|
||||
/// @version 0.0.1
|
||||
/// @date 2023-09-08
|
||||
/// @brief Low Level SPI driver
|
||||
///-------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifndef __ALIF_DCD_REG_H__
|
||||
#define __ALIF_DCD_REG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
#define _rw volatile uint32_t
|
||||
#define __w volatile uint32_t
|
||||
#define __r volatile const uint32_t
|
||||
|
||||
volatile struct {
|
||||
union {
|
||||
_rw gsbuscfg0;
|
||||
struct {
|
||||
_rw incrbrstena : 1;
|
||||
_rw incr4brstena : 1;
|
||||
_rw incr8brstena : 1;
|
||||
_rw incr16brstena : 1;
|
||||
_rw incr32brstena : 1;
|
||||
_rw incr64brstena : 1;
|
||||
_rw incr128brstena : 1;
|
||||
_rw incr256brstena : 1;
|
||||
__r : 2;
|
||||
_rw desbigend : 1;
|
||||
_rw datbigend : 1;
|
||||
__r : 4;
|
||||
_rw deswrreqinfo : 4;
|
||||
_rw datwrreqinfo : 4;
|
||||
_rw desrdreqinfo : 4;
|
||||
_rw datrdreqinfo : 4;
|
||||
} gsbuscfg0_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gsbuscfg1;
|
||||
struct {
|
||||
__r : 8;
|
||||
_rw pipetranslimit : 4;
|
||||
_rw en1kpage : 1;
|
||||
__r : 19;
|
||||
} gsbuscfg1_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32;
|
||||
|
||||
union {
|
||||
_rw gctl;
|
||||
struct {
|
||||
_rw dsblclkgtng : 1;
|
||||
_rw gblhibernationen : 1;
|
||||
__r : 1;
|
||||
_rw disscramble : 1;
|
||||
_rw scaledown : 2;
|
||||
_rw ramclksel : 2;
|
||||
__r : 2;
|
||||
_rw sofitpsync : 1;
|
||||
_rw coresoftreset : 1;
|
||||
_rw prtcapdir : 2;
|
||||
_rw frmscldwn : 2;
|
||||
__r : 1;
|
||||
_rw bypssetaddr : 1;
|
||||
__r : 14;
|
||||
} gctl_b;
|
||||
};
|
||||
|
||||
__r : 32;
|
||||
|
||||
union {
|
||||
_rw gsts;
|
||||
struct {
|
||||
__r curmod : 2;
|
||||
__r : 2;
|
||||
_rw buserraddrvld : 1;
|
||||
_rw csrtimeout : 1;
|
||||
__r device_ip : 1;
|
||||
__r host_ip : 1;
|
||||
__r adp_ip : 1;
|
||||
__r bc_ip : 1;
|
||||
__r otg_ip : 1;
|
||||
__r ssic_ip : 1;
|
||||
__r : 8;
|
||||
__r cbelt : 12;
|
||||
} gsts_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw guctl1;
|
||||
struct {
|
||||
_rw loa_filter_en : 1;
|
||||
_rw ovrld_l1_susp_com : 1;
|
||||
_rw hc_parchk_disable : 1;
|
||||
_rw hc_errata_enable : 1;
|
||||
_rw l1_susp_thrld_for_host : 4;
|
||||
_rw l1_susp_thrld_en_for_host : 1;
|
||||
_rw dev_hs_nyet_bulk_spr : 1;
|
||||
_rw resume_opmode_hs_host : 1;
|
||||
__r : 1;
|
||||
_rw disusb2refclkgtng : 1;
|
||||
__r : 2;
|
||||
_rw parkmode_disable_fsls : 1;
|
||||
_rw parkmode_disable_hs : 1;
|
||||
__r : 1;
|
||||
_rw nak_per_enh_hs : 1;
|
||||
_rw nak_per_enh_fs : 1;
|
||||
_rw dev_lsp_tail_lock_dis : 1;
|
||||
_rw ip_gap_add_on : 2;
|
||||
_rw dev_l1_exit_by_hw : 1;
|
||||
__r : 2;
|
||||
_rw dev_trb_out_spr_ind : 1;
|
||||
_rw tx_ipgap_linecheck_dis : 1;
|
||||
_rw filter_se0_fsls_eop : 1;
|
||||
__r : 1;
|
||||
_rw dev_decouple_l1l2_evt : 1;
|
||||
} guctl1_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gsnpsid;
|
||||
};
|
||||
|
||||
__r : 32;
|
||||
|
||||
union {
|
||||
_rw guid;
|
||||
struct {
|
||||
_rw userid : 32;
|
||||
} guid_b;
|
||||
};
|
||||
|
||||
union { // <- host only, leaving unimplemented for now [FIXME]
|
||||
_rw guctl;
|
||||
struct {
|
||||
} guctl_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gbuserraddrlo;
|
||||
struct {
|
||||
_rw buserraddr : 32;
|
||||
} gbuserraddrlo_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gbuserraddrhi;
|
||||
struct {
|
||||
_rw buserraddr : 32;
|
||||
} gbuserraddrhi_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32;
|
||||
|
||||
__r ghwparams[8];
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x9C here
|
||||
|
||||
union {
|
||||
_rw guctl2;
|
||||
struct {
|
||||
__r : 11;
|
||||
_rw disablecfc : 1;
|
||||
_rw enableepcacheevict : 1;
|
||||
__r : 1;
|
||||
_rw rst_actbitlater : 1;
|
||||
__r : 4;
|
||||
_rw en_hp_pm_timer : 7;
|
||||
__r : 6;
|
||||
} guctl2_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x100 here
|
||||
|
||||
union {
|
||||
_rw gusb2phycfg0;
|
||||
struct {
|
||||
_rw toutcal : 3;
|
||||
_rw phyif : 1;
|
||||
__r ulpi_utmi_sel : 1;
|
||||
__r fsintf : 1;
|
||||
_rw suspendusb20 : 1;
|
||||
_rw physel : 1;
|
||||
_rw enblslpm : 1;
|
||||
_rw xcvrdly : 1;
|
||||
_rw usbtrdtim : 4;
|
||||
__r : 5;
|
||||
_rw lsipd : 3;
|
||||
_rw lstrd : 3;
|
||||
_rw ovrd_fsls_disc_time : 1;
|
||||
__r inv_sel_hsic : 1;
|
||||
__r hsic_con_width_adj : 2;
|
||||
_rw ulpi_lpm_with_opmode_chk : 1;
|
||||
_rw u2_freeclk_exists : 1;
|
||||
_rw physoftrst : 1;
|
||||
} gusb2phycfg0_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x200 here
|
||||
|
||||
union {
|
||||
_rw gtxfifosiz[4];
|
||||
struct {
|
||||
_rw txfdep : 16;
|
||||
_rw txfstaddr : 16;
|
||||
} gtxfifosiz_b[4];
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x280 here
|
||||
|
||||
union {
|
||||
_rw grxfifosiz[4];
|
||||
struct {
|
||||
_rw rxfdep : 16;
|
||||
_rw rxfstaddr : 16;
|
||||
} grxfifosiz_b[4];
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x300 here
|
||||
|
||||
union {
|
||||
_rw gevntadrlo0;
|
||||
struct {
|
||||
_rw evntadrlo : 32;
|
||||
} gevntadrlo0_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gevntadrhi0;
|
||||
struct {
|
||||
_rw evntadrhi : 32;
|
||||
} gevntadrhi0_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gevntsiz0;
|
||||
struct {
|
||||
_rw eventsiz : 16;
|
||||
__r : 15;
|
||||
_rw evntintrptmask : 1;
|
||||
} gevntsiz0_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw gevntcount0;
|
||||
struct {
|
||||
_rw evntcount : 16;
|
||||
__r : 15;
|
||||
_rw evnt_handler_busy : 1;
|
||||
} gevntcount0_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x500 here
|
||||
|
||||
__r ghwparams8;
|
||||
|
||||
__r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x510 here
|
||||
|
||||
union {
|
||||
_rw gtxfifopridev;
|
||||
struct {
|
||||
_rw gtxfifopridev : 4;
|
||||
__r : 28;
|
||||
} gtxfifopridev_b;
|
||||
};
|
||||
|
||||
__r : 32;
|
||||
|
||||
union {
|
||||
_rw gtxfifoprihst;
|
||||
struct {
|
||||
_rw gtxfifoprihst : 2;
|
||||
__r : 30;
|
||||
} gtxfifoprihst_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw grxfifoprihst;
|
||||
struct {
|
||||
_rw grxfifoprihst : 2;
|
||||
__r : 30;
|
||||
} grxfifoprihst_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x530 here
|
||||
|
||||
union {
|
||||
_rw gfladj;
|
||||
struct {
|
||||
_rw gfladj_30mhz : 6;
|
||||
__r : 1;
|
||||
_rw gfladj_30mhz_sdbnd_sel : 1;
|
||||
_rw gfladj_refclk_fladj : 14;
|
||||
__r : 1;
|
||||
_rw gfladj_refclk_lpm_sel : 1;
|
||||
_rw gfladj_refclk_240mhz_decr : 7;
|
||||
_rw gfladj_refclk_240mhzdecr_pls1 : 1;
|
||||
} gfladj_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x540 here
|
||||
|
||||
union {
|
||||
_rw gusb2rhbctl0;
|
||||
struct {
|
||||
_rw ovrd_l1timeout : 4;
|
||||
__r : 28;
|
||||
} gusb2rhbctl0_b;
|
||||
};
|
||||
|
||||
} *ugbl = (void *) (USB_BASE + 0xC100);
|
||||
|
||||
volatile struct {
|
||||
union {
|
||||
_rw dcfg;
|
||||
struct {
|
||||
_rw devspd : 3;
|
||||
_rw devaddr : 7;
|
||||
__r : 2;
|
||||
_rw intrnum : 5;
|
||||
_rw nump : 5;
|
||||
_rw lpmcap : 1;
|
||||
_rw ignstrmpp : 1;
|
||||
__r : 8;
|
||||
} dcfg_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw dctl;
|
||||
struct {
|
||||
__r : 1;
|
||||
_rw tstctl : 4;
|
||||
__w ulstchngreq : 4;
|
||||
__r : 7;
|
||||
_rw css : 1;
|
||||
_rw crs : 1;
|
||||
_rw l1hibernationen : 1;
|
||||
_rw keepconnect : 1;
|
||||
_rw lpm_nyet_thres : 4;
|
||||
_rw hirdthres : 5;
|
||||
__r : 1;
|
||||
_rw csftrst : 1;
|
||||
_rw run_stop : 1;
|
||||
} dctl_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw devten;
|
||||
struct {
|
||||
_rw dissconnevten : 1;
|
||||
_rw usbrstevten : 1;
|
||||
_rw connectdoneevten : 1;
|
||||
_rw ulstcngen : 1;
|
||||
_rw wkupevten : 1;
|
||||
_rw hibernationreqevten : 1;
|
||||
_rw u3l2l1suspen : 1;
|
||||
_rw softevten : 1;
|
||||
_rw l1suspen : 1;
|
||||
_rw errticerrevten : 1;
|
||||
__r : 2;
|
||||
_rw vendevtstrcvden : 1;
|
||||
__r : 1;
|
||||
_rw l1wkupevten : 1;
|
||||
__r : 1;
|
||||
_rw eccerren : 1;
|
||||
__r : 15;
|
||||
} devten_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw dsts;
|
||||
struct {
|
||||
__r connectspd : 3;
|
||||
__r soffn : 14;
|
||||
__r rxfifoempty : 1;
|
||||
__r usblnkst : 4;
|
||||
__r devctrlhlt : 1;
|
||||
__r coreidle : 1;
|
||||
__r sss : 1;
|
||||
__r rss : 1;
|
||||
__r : 2;
|
||||
_rw sre : 1;
|
||||
__r dcnrd : 1;
|
||||
__r : 2;
|
||||
} dsts_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw dgcmdpar;
|
||||
struct {
|
||||
_rw parameter : 32;
|
||||
} dgcmdpar_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw dgcmd;
|
||||
struct {
|
||||
_rw cmdtyp : 8;
|
||||
_rw cmdioc : 1;
|
||||
__r : 1;
|
||||
_rw cmdact : 1;
|
||||
__r : 1;
|
||||
__r cmdstatus : 4;
|
||||
__r : 16;
|
||||
} dgcmd_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32;
|
||||
|
||||
union {
|
||||
_rw dalepena;
|
||||
struct {
|
||||
_rw usbactep : 32;
|
||||
} dalepena_b;
|
||||
};
|
||||
|
||||
__r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x100 here
|
||||
|
||||
struct {
|
||||
union {
|
||||
_rw par2;
|
||||
struct {
|
||||
_rw parameter : 32;
|
||||
} par2_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw par1;
|
||||
struct {
|
||||
_rw parameter : 32;
|
||||
} par1_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw par0;
|
||||
struct {
|
||||
_rw parameter : 32;
|
||||
} par0_b;
|
||||
};
|
||||
|
||||
union {
|
||||
_rw depcmd;
|
||||
struct {
|
||||
_rw cmdtyp : 4;
|
||||
__r : 4;
|
||||
_rw cmdioc : 1;
|
||||
__r : 1;
|
||||
_rw cmdact : 1;
|
||||
_rw hipri_forcerm : 1;
|
||||
_rw cmdstatus : 4;
|
||||
_rw commandparam : 16;
|
||||
} depcmd_b;
|
||||
};
|
||||
} depcmd[8];
|
||||
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
__r : 32; __r : 32; __r : 32; __r : 32;
|
||||
|
||||
// base + 0x300 here
|
||||
|
||||
union {
|
||||
_rw dev_imod0;
|
||||
struct {
|
||||
_rw device_imodi : 16;
|
||||
_rw device_imocd : 16;
|
||||
} dev_imod0_b;
|
||||
};
|
||||
} *udev = (void *) (USB_BASE + 0xC700);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
typedef union {
|
||||
_rw val : 32;
|
||||
struct {
|
||||
_rw sig : 8;
|
||||
_rw evt : 5;
|
||||
__r : 3;
|
||||
_rw info : 9;
|
||||
__r : 7;
|
||||
} devt;
|
||||
struct {
|
||||
_rw sig : 1;
|
||||
_rw ep : 5;
|
||||
_rw evt : 4;
|
||||
__r : 2;
|
||||
_rw sts : 4;
|
||||
_rw par : 16;
|
||||
} depevt;
|
||||
} evt_t;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
enum {
|
||||
CMDTYP_RESERVED = 0,
|
||||
CMDTYP_DEPCFG,
|
||||
CMDTYP_DEPXFERCFG,
|
||||
CMDTYP_DEPGETSTATE,
|
||||
CMDTYP_DEPSSTALL,
|
||||
CMDTYP_DEPCSTALL,
|
||||
CMDTYP_DEPSTRTXFER,
|
||||
CMDTYP_DEPUPDXFER,
|
||||
CMDTYP_DEPENDXFER,
|
||||
CMDTYP_DEPSTARTCFG
|
||||
} DEPCMD_CMDTYP;
|
||||
|
||||
enum {
|
||||
DEVT_DISCONNEVT = 0,
|
||||
DEVT_USBRST,
|
||||
DEVT_CONNECTDONE,
|
||||
DEVT_ULSTCHNG,
|
||||
DEVT_WKUPEVT,
|
||||
// DEVT_HIBRQ not implemented
|
||||
DEVT_USBSUSP = 6,
|
||||
DEVT_SOF,
|
||||
DEVT_L1SUSP,
|
||||
DEVT_ERRTICERR,
|
||||
DEVT_CMDCMPLT,
|
||||
DEVT_EVNTOVERFLOW,
|
||||
DEVT_VNDDEVTSTRCVED,
|
||||
// reserved
|
||||
DEVT_L1RESM = 14,
|
||||
// reserved
|
||||
DEVT_ECCERR = 16
|
||||
} DEVT;
|
||||
|
||||
enum {
|
||||
// reserved
|
||||
DEPEVT_XFERCOMPLETE = 1,
|
||||
DEPEVT_XFERINPROGRESS,
|
||||
DEPEVT_XFERNOTREADY,
|
||||
// not implemented
|
||||
DEPEVT_STREAMEVT = 6,
|
||||
DEPEVT_EPCMDCMPLT
|
||||
} DEPEVT;
|
||||
|
||||
enum {
|
||||
// reserved
|
||||
TRBCTL_NORMAL = 1,
|
||||
TRBCTL_CTL_SETUP,
|
||||
TRBCTL_CTL_STAT2,
|
||||
TRBCTL_CTL_STAT3,
|
||||
TRBCTL_CTL_DATA,
|
||||
TRBCTL_ISO_FIRST,
|
||||
TRBCTL_ISO,
|
||||
TRBCTL_LINK,
|
||||
TRBCTL_NORMAL_ZLP
|
||||
} TRBCTL;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
#endif // __ALIF_DCD_REG_H__
|
||||
688
ports/alif/tinyusb_port/tusb_alif_dcd.c
Normal file
688
ports/alif/tinyusb_port/tusb_alif_dcd.c
Normal file
@@ -0,0 +1,688 @@
|
||||
// *FORMAT-OFF*
|
||||
/* Copyright (C) 2024 Alif Semiconductor - All Rights Reserved.
|
||||
* Use, distribution and modification of this code is permitted under the
|
||||
* terms stated in the Alif Semiconductor Software License Agreement
|
||||
*
|
||||
* You should have received a copy of the Alif Semiconductor Software
|
||||
* License Agreement with this file. If not, please write to:
|
||||
* contact@alifsemi.com, or visit: https://alifsemi.com/license
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tusb_option.h"
|
||||
|
||||
#if CFG_TUD_ENABLED
|
||||
|
||||
#if defined(CORE_M55_HE)
|
||||
#include "M55_HE.h"
|
||||
#elif defined(CORE_M55_HP)
|
||||
#include "M55_HP.h"
|
||||
#else
|
||||
#error "Unsupported core!"
|
||||
#endif
|
||||
|
||||
#include "device/dcd.h"
|
||||
|
||||
#include "alif_dcd_reg.h"
|
||||
|
||||
#include "clk.h"
|
||||
#include "power.h"
|
||||
|
||||
// #define TUSB_ALIF_DEBUG
|
||||
// #define TUSB_ALIF_DEBUG_DEPTH (2048)
|
||||
|
||||
#if defined(TUSB_ALIF_DEBUG)
|
||||
#if (1 < TUSB_ALIF_DEBUG_DEPTH)
|
||||
#define LOG(...) memset(logbuf[bi % TUSB_ALIF_DEBUG_DEPTH], ' ', 48);\
|
||||
snprintf(logbuf[(bi++) % TUSB_ALIF_DEBUG_DEPTH], 48, __VA_ARGS__);
|
||||
char logbuf[TUSB_ALIF_DEBUG_DEPTH][48];
|
||||
int bi = 0;
|
||||
#else
|
||||
#define LOG(...) memset(logbuf, ' ', 48);\
|
||||
snprintf(logbuf, 48, __VA_ARGS__)
|
||||
char logbuf[48];
|
||||
#endif
|
||||
#else
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
/// Structs and Buffers --------------------------------------------------------
|
||||
|
||||
static uint32_t _evnt_buf[1024] CFG_TUSB_MEM_SECTION __attribute__((aligned(4096))); // [TODO] runtime alloc
|
||||
static volatile uint32_t* _evnt_tail;
|
||||
|
||||
static uint8_t _ctrl_buf[64] CFG_TUSB_MEM_SECTION __attribute__((aligned(32))); // [TODO] runtime alloc
|
||||
static uint32_t _xfer_trb[8][4] CFG_TUSB_MEM_SECTION __attribute__((aligned(32))); // [TODO] runtime alloc
|
||||
static uint16_t _xfer_bytes[8];
|
||||
static bool _ctrl_long_data = false;
|
||||
static bool _xfer_cfgd = false;
|
||||
// static bool _addr_req = false;
|
||||
static uint32_t _sts_stage = 0;
|
||||
|
||||
/// Private Functions ----------------------------------------------------------
|
||||
|
||||
static uint8_t _dcd_cmd_wait(uint8_t ep, uint8_t typ, uint16_t param);
|
||||
static uint8_t _dcd_start_xfer(uint8_t ep, void* buf, uint32_t size, uint8_t type);
|
||||
|
||||
static void _dcd_handle_depevt(uint8_t ep, uint8_t evt, uint8_t sts, uint16_t par);
|
||||
static void _dcd_handle_devt(uint8_t evt, uint16_t info);
|
||||
|
||||
/// API Extension --------------------------------------------------------------
|
||||
|
||||
void dcd_uninit(void);
|
||||
|
||||
/// Device Setup ---------------------------------------------------------------
|
||||
|
||||
// Initializes the USB peripheral for device mode and enables it.
|
||||
// This function should enable internal D+/D- pull-up for enumeration.
|
||||
void dcd_init(uint8_t rhport)
|
||||
{
|
||||
// enable 20mhz clock
|
||||
enable_cgu_clk20m();
|
||||
// enable usb peripheral clock
|
||||
enable_usb_periph_clk();
|
||||
// power up usb phy
|
||||
enable_usb_phy_power();
|
||||
// disable usb phy isolation
|
||||
disable_usb_phy_isolation();
|
||||
// clear usb phy power-on-reset signal
|
||||
CLKCTL_PER_MST->USB_CTRL2 &= ~(1 << 8);
|
||||
|
||||
// force stop/disconnect
|
||||
udev->dctl_b.run_stop = 0;
|
||||
|
||||
// dctl set csftrst to 1 and wait for 0
|
||||
udev->dctl_b.csftrst = 1;
|
||||
while(0 != udev->dctl_b.csftrst);
|
||||
|
||||
sys_busy_loop_us(50000);
|
||||
ugbl->gctl_b.coresoftreset = 1;
|
||||
ugbl->gusb2phycfg0_b.physoftrst = 1;
|
||||
sys_busy_loop_us(50000);
|
||||
ugbl->gusb2phycfg0_b.physoftrst = 0;
|
||||
sys_busy_loop_us(50000);
|
||||
ugbl->gctl_b.coresoftreset = 0;
|
||||
sys_busy_loop_us(50000);
|
||||
|
||||
ugbl->gsbuscfg0 = 0x00000009;
|
||||
// ugbl->gusb2phycfg0 = 0x4000154F; // [TODO] document as bits
|
||||
uint32_t reg = ugbl->gusb2phycfg0;
|
||||
reg &= ~((1 << 3) | (1 << 4) | (0xF << 10)); // clear phyif, ulpi_utmi_sel and usbtrdtim
|
||||
reg |= ((1 << 3) | (5 << 10));
|
||||
ugbl->gusb2phycfg0 = reg;
|
||||
|
||||
// set device speed (USBHS only)
|
||||
udev->dcfg_b.devspd = 0x0; // HS, this will need #if condition [TODO]
|
||||
|
||||
// allocate ring buffer for events
|
||||
memset(_evnt_buf, 0, sizeof(_evnt_buf));
|
||||
RTSS_CleanDCache_by_Addr(_evnt_buf, sizeof(_evnt_buf));
|
||||
_evnt_tail = _evnt_buf;
|
||||
ugbl->gevntadrlo0 = (uint32_t) LocalToGlobal(_evnt_buf);
|
||||
ugbl->gevntsiz0_b.eventsiz = (uint32_t) sizeof(_evnt_buf);
|
||||
ugbl->gevntcount0_b.evntcount = 0;
|
||||
|
||||
// write devten to enable usb reset, conn done, link state change...
|
||||
udev->devten_b.dissconnevten = 1;
|
||||
udev->devten_b.usbrstevten = 1;
|
||||
udev->devten_b.connectdoneevten = 1;
|
||||
udev->devten_b.ulstcngen = 1;
|
||||
|
||||
// begin endpoint setup
|
||||
_dcd_cmd_wait(0, CMDTYP_DEPSTARTCFG, 0);
|
||||
|
||||
// configure CONTROL IN and OUT eps
|
||||
udev->depcmd[0].par1 = (0 << 25) | (1 << 10) | (1 << 8);
|
||||
udev->depcmd[0].par0 = (0 << 22) | (0 << 17) | (512 << 3) | (0 << 1);
|
||||
_dcd_cmd_wait(0, CMDTYP_DEPCFG, 0);
|
||||
|
||||
udev->depcmd[1].par1 = (1 << 25) | (1 << 10) | (1 << 8);
|
||||
udev->depcmd[1].par0 = (0 << 22) | (0 << 17) | (512 << 3) | (0 << 1);
|
||||
_dcd_cmd_wait(1, CMDTYP_DEPCFG, 0);
|
||||
|
||||
// set initial xfer configuration for CONTROL eps
|
||||
udev->depcmd[0].par0 = 1;
|
||||
_dcd_cmd_wait(0, CMDTYP_DEPXFERCFG, 0);
|
||||
|
||||
udev->depcmd[1].par0 = 1;
|
||||
_dcd_cmd_wait(1, CMDTYP_DEPXFERCFG, 0);
|
||||
|
||||
// enable pull-ups
|
||||
dcd_connect(rhport);
|
||||
|
||||
// prepare trb for the first setup packet
|
||||
memset(_ctrl_buf, 0, sizeof(_ctrl_buf));
|
||||
_xfer_trb[0][0] = (uint32_t) LocalToGlobal(_ctrl_buf);
|
||||
_xfer_trb[0][1] = 0;
|
||||
_xfer_trb[0][2] = 8;
|
||||
_xfer_trb[0][3] = (1 << 11) | (1 << 10) | (TRBCTL_CTL_SETUP << 4) | (1 << 1) | (1 << 0);
|
||||
RTSS_CleanDCache_by_Addr(_xfer_trb[0], sizeof(_xfer_trb[0]));
|
||||
|
||||
// send trb to the usb dma
|
||||
udev->depcmd[0].par1 = (uint32_t) LocalToGlobal(_xfer_trb[0]);
|
||||
udev->depcmd[0].par0 = 0;
|
||||
_dcd_cmd_wait(0, CMDTYP_DEPSTRTXFER, 0);
|
||||
|
||||
// enable ep event interrupts for CONTROL OUT and IN
|
||||
udev->dalepena_b.usbactep = (1 << 1) | (1 << 0);
|
||||
|
||||
// enable interrupts in the NVIC
|
||||
#if !defined(TUSB_ALIF_NO_IRQ_CFG)
|
||||
NVIC_ClearPendingIRQ(USB_IRQ_IRQn);
|
||||
NVIC_SetPriority(USB_IRQ_IRQn, 5);
|
||||
#endif
|
||||
dcd_int_enable(rhport);
|
||||
}
|
||||
|
||||
|
||||
// Processes all the hardware generated events e.g bus reset, new data packet
|
||||
// from host... It will be called by application in the MCU USB interrupt handler.
|
||||
void dcd_int_handler(uint8_t rhport)
|
||||
{
|
||||
LOG("%010u IRQ enter, evntcount %u", DWT->CYCCNT, ugbl->gevntcount0_b.evntcount);
|
||||
|
||||
// process failures first
|
||||
if (ugbl->gsts_b.device_ip) {
|
||||
if (ugbl->gsts_b.csrtimeout || ugbl->gsts_b.buserraddrvld) {
|
||||
// buserraddrvld is usually set when USB tries to write to protected
|
||||
// memory region. Check linker script to ensure USB event buffer and
|
||||
// TRBs reside in bulk memory or other NS-allowed region
|
||||
__BKPT(0);
|
||||
}
|
||||
}
|
||||
|
||||
// cycle through event queue
|
||||
// evaluate on every iteration to prevent unnecessary isr exit/reentry
|
||||
while (0 < ugbl->gevntcount0_b.evntcount) {
|
||||
RTSS_InvalidateDCache_by_Addr(_evnt_buf, sizeof(_evnt_buf));
|
||||
volatile evt_t e = {.val = *_evnt_tail++};
|
||||
|
||||
LOG("%010u IRQ loop, evntcount %u evnt %08x", DWT->CYCCNT,
|
||||
ugbl->gevntcount0_b.evntcount, e.val);
|
||||
|
||||
// wrap around
|
||||
if (_evnt_tail >= (_evnt_buf + 1024)) _evnt_tail = _evnt_buf;
|
||||
|
||||
// dispatch the right handler for the event type
|
||||
if (0 == e.depevt.sig) { // DEPEVT
|
||||
_dcd_handle_depevt(e.depevt.ep, e.depevt.evt, e.depevt.sts, e.depevt.par);
|
||||
} else if (1 == e.devt.sig) { // DEVT
|
||||
_dcd_handle_devt(e.devt.evt, e.devt.info);
|
||||
} else {
|
||||
// bad event??
|
||||
LOG("Unknown event %u", e.val);
|
||||
__BKPT(0);
|
||||
}
|
||||
|
||||
// consume one event
|
||||
ugbl->gevntcount0 = 4;
|
||||
}
|
||||
|
||||
LOG("%010u IRQ exit, evntcount %u", DWT->CYCCNT, ugbl->gevntcount0_b.evntcount);
|
||||
}
|
||||
|
||||
|
||||
// Enables the USB device interrupt.
|
||||
// May be used to prevent concurrency issues when mutating data structures
|
||||
// shared between main code and the interrupt handler.
|
||||
void dcd_int_enable (uint8_t rhport)
|
||||
{
|
||||
NVIC_EnableIRQ(USB_IRQ_IRQn);
|
||||
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
// Disables the USB device interrupt.
|
||||
// May be used to prevent concurrency issues when mutating data structures
|
||||
// shared between main code and the interrupt handler.
|
||||
void dcd_int_disable(uint8_t rhport)
|
||||
{
|
||||
NVIC_DisableIRQ(USB_IRQ_IRQn);
|
||||
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
// Receive Set Address request, mcu port must also include status IN response.
|
||||
// If your peripheral automatically changes address during enumeration you may
|
||||
// leave this empty and also no queue an event for the corresponding SETUP packet.
|
||||
void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
|
||||
{
|
||||
LOG("%010u >%s", DWT->CYCCNT, __func__);
|
||||
|
||||
udev->dcfg_b.devaddr = dev_addr;
|
||||
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
|
||||
}
|
||||
|
||||
// Called to remote wake up host when suspended (e.g hid keyboard)
|
||||
void dcd_remote_wakeup(uint8_t rhport)
|
||||
{
|
||||
LOG("%010u >%s", DWT->CYCCNT, __func__);
|
||||
}
|
||||
|
||||
// Connect by enabling internal pull-up resistor on D+/D-
|
||||
void dcd_connect(uint8_t rhport)
|
||||
{
|
||||
udev->dctl_b.run_stop = 1;
|
||||
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
// Disconnect by disabling internal pull-up resistor on D+/D-
|
||||
void dcd_disconnect(uint8_t rhport)
|
||||
{
|
||||
// [TODO] clear all xfers and eps first
|
||||
|
||||
udev->dctl_b.run_stop = 0;
|
||||
|
||||
(void) rhport;
|
||||
}
|
||||
|
||||
// Enable/Disable Start-of-frame interrupt. Default is disabled
|
||||
void dcd_sof_enable(uint8_t rhport, bool en)
|
||||
{
|
||||
LOG("%010u >%s", DWT->CYCCNT, __func__);
|
||||
}
|
||||
|
||||
|
||||
/// Endpoint Management --------------------------------------------------------
|
||||
|
||||
// Invoked when a control transfer's status stage is complete.
|
||||
// May help DCD to prepare for next control transfer, this API is optional.
|
||||
void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * request)
|
||||
{
|
||||
LOG("%010u >%s", DWT->CYCCNT, __func__);
|
||||
|
||||
_ctrl_long_data = false;
|
||||
_dcd_start_xfer(TUSB_DIR_OUT, _ctrl_buf, 8, TRBCTL_CTL_SETUP);
|
||||
}
|
||||
|
||||
// Opening an endpoint is done for all non-control endpoints once the host picks
|
||||
// a configuration that the device should use.
|
||||
// At this point, the endpoint should be enabled in the peripheral and
|
||||
// configured to match the endpoint descriptor.
|
||||
// Pay special attention to the direction of the endpoint you can get from the
|
||||
// helper methods above. It will likely change what registers you are setting.
|
||||
// Also make sure to enable endpoint specific interrupts.
|
||||
bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
|
||||
{
|
||||
LOG("%010u >%s %u %s %u %u", DWT->CYCCNT, __func__, desc_ep->bEndpointAddress,
|
||||
desc_ep->bmAttributes.xfer == TUSB_XFER_BULK ? "bulk" : "int",
|
||||
desc_ep->wMaxPacketSize, desc_ep->bInterval);
|
||||
|
||||
if (TUSB_XFER_ISOCHRONOUS == desc_ep->bmAttributes.xfer)
|
||||
return false;
|
||||
|
||||
uint8_t ep = (tu_edpt_number(desc_ep->bEndpointAddress) << 1) |
|
||||
tu_edpt_dir(desc_ep->bEndpointAddress);
|
||||
|
||||
// [TODO] verify that the num doesn't exceed hw max
|
||||
|
||||
if (false == _xfer_cfgd) {
|
||||
_dcd_cmd_wait(0, CMDTYP_DEPSTARTCFG, 2);
|
||||
_xfer_cfgd = true;
|
||||
}
|
||||
|
||||
uint8_t fifo_num = TUSB_DIR_IN == tu_edpt_dir(desc_ep->bEndpointAddress) ?
|
||||
tu_edpt_number(desc_ep->bEndpointAddress) : 0;
|
||||
uint8_t interval = 0 < desc_ep->bInterval ? (desc_ep->bInterval - 1) : 0;
|
||||
|
||||
udev->depcmd[ep].par1 = (ep << 25) | (interval << 16) |
|
||||
(1 << 10) | (1 << 8);
|
||||
udev->depcmd[ep].par0 = (0 << 30) | (0 << 22) | (fifo_num << 17) |
|
||||
((desc_ep->wMaxPacketSize & 0x7FF) << 3) |
|
||||
(desc_ep->bmAttributes.xfer << 1);
|
||||
|
||||
_dcd_cmd_wait(ep, CMDTYP_DEPCFG, 0);
|
||||
udev->depcmd[ep].par0 = 1;
|
||||
_dcd_cmd_wait(ep, CMDTYP_DEPXFERCFG, 0);
|
||||
|
||||
udev->dalepena_b.usbactep |= (1 << ep);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Close all non-control endpoints, cancel all pending transfers if any.
|
||||
// Invoked when switching from a non-zero Configuration by SET_CONFIGURE therefore
|
||||
// required for multiple configuration support.
|
||||
void dcd_edpt_close_all(uint8_t rhport)
|
||||
{
|
||||
LOG("%010u >%s", DWT->CYCCNT, __func__);
|
||||
}
|
||||
|
||||
// Close an endpoint. his function is used for implementing alternate settings.
|
||||
// After calling this, the device should not respond to any packets directed
|
||||
// towards this endpoint. When called, this function must abort any transfers in
|
||||
// progress through this endpoint, before returning.
|
||||
// Implementation is optional. Must be called from the USB task.
|
||||
// Interrupts could be disabled or enabled during the call.
|
||||
void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) TU_ATTR_WEAK;
|
||||
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to
|
||||
// notify the stack
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
// DEPSTRTXFER command
|
||||
LOG("%010u >%s %u %x %u", DWT->CYCCNT, __func__, ep_addr, (uint32_t) buffer, total_bytes);
|
||||
|
||||
uint8_t ep = (tu_edpt_number(ep_addr) << 1) | tu_edpt_dir(ep_addr);
|
||||
|
||||
switch (ep) {
|
||||
case 0: { // CONTROL OUT
|
||||
if (0 < total_bytes) {
|
||||
// DATA OUT request
|
||||
_xfer_bytes[0] = total_bytes;
|
||||
_dcd_start_xfer(0, buffer, total_bytes, TRBCTL_CTL_STAT3);
|
||||
} else {
|
||||
// TinyUSB explicitly requests STATUS OUT fetch after DATA IN
|
||||
if (2 == ++_sts_stage) {
|
||||
_sts_stage = 0;
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(0, TUSB_DIR_OUT),
|
||||
0, XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case 1: { // CONTROL IN
|
||||
_xfer_bytes[1] = total_bytes;
|
||||
|
||||
if (0 < total_bytes) {
|
||||
RTSS_CleanDCache_by_Addr(buffer, total_bytes);
|
||||
uint8_t type = _ctrl_long_data ? TRBCTL_NORMAL : TRBCTL_CTL_DATA;
|
||||
if (64 == total_bytes) {
|
||||
_ctrl_long_data = true;
|
||||
}
|
||||
_dcd_start_xfer(1, buffer, total_bytes, type);
|
||||
} else {
|
||||
// status events are handled directly from the ISR when USB
|
||||
// controller triggers XferNotReady event for status stage
|
||||
|
||||
if (2 == ++_sts_stage) {
|
||||
_sts_stage = 0;
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(0, TUSB_DIR_IN),
|
||||
0, XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
// dcd_event_xfer_complete(rhport, tu_edpt_addr(0, TUSB_DIR_IN),
|
||||
// 0, XFER_RESULT_SUCCESS, false);
|
||||
}
|
||||
} break;
|
||||
default: { // DATA EPs (BULK & INTERRUPT only)
|
||||
_xfer_bytes[ep] = total_bytes;
|
||||
if (TUSB_DIR_IN == tu_edpt_dir(ep_addr)) {
|
||||
RTSS_CleanDCache_by_Addr(buffer, total_bytes);
|
||||
} else {
|
||||
total_bytes = 512; // temporary hack, controller requires max
|
||||
// size requests on OUT endpoints [FIXME]
|
||||
}
|
||||
uint8_t ret = _dcd_start_xfer(ep, buffer, total_bytes,
|
||||
total_bytes ? TRBCTL_NORMAL : TRBCTL_NORMAL_ZLP);
|
||||
LOG("start xfer sts %u", ret);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Submit a transfer using fifo, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
// This API is optional, may be useful for register-based for transferring data.
|
||||
bool dcd_edpt_xfer_fifo(uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes) TU_ATTR_WEAK;
|
||||
|
||||
// Stall endpoint, any queuing transfer should be removed from endpoint
|
||||
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
// DEPSSTALL command
|
||||
LOG(">%s", __func__);
|
||||
|
||||
uint8_t ep = (tu_edpt_number(ep_addr) << 1) | tu_edpt_dir(ep_addr);
|
||||
|
||||
_dcd_cmd_wait(ep, CMDTYP_DEPSSTALL, 0);
|
||||
|
||||
if (0 == tu_edpt_number(ep_addr)) {
|
||||
_ctrl_long_data = false;
|
||||
_dcd_start_xfer(TUSB_DIR_OUT, _ctrl_buf, 8, TRBCTL_CTL_SETUP);
|
||||
}
|
||||
}
|
||||
|
||||
// clear stall, data toggle is also reset to DATA0
|
||||
// This API never calls with control endpoints, since it is auto cleared when
|
||||
// receiving setup packet
|
||||
void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
// DEPCSTALL command
|
||||
LOG(">%s", __func__);
|
||||
|
||||
uint8_t ep = (tu_edpt_number(ep_addr) << 1) | tu_edpt_dir(ep_addr);
|
||||
|
||||
_dcd_cmd_wait(ep, CMDTYP_DEPCSTALL, 0);
|
||||
}
|
||||
|
||||
void dcd_uninit(void)
|
||||
{
|
||||
CLKCTL_PER_MST->USB_CTRL2 |= 1 << 8; // set usb phy power-on-reset signal
|
||||
enable_usb_phy_isolation(); // enable usb phy isolation
|
||||
disable_usb_phy_power(); // power down usb phy
|
||||
disable_usb_periph_clk(); // disable usb peripheral clock
|
||||
}
|
||||
|
||||
void USB_IRQHandler(void)
|
||||
{
|
||||
dcd_int_handler(TUD_OPT_RHPORT);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t _dcd_cmd_wait(uint8_t ep, uint8_t typ, uint16_t param)
|
||||
{
|
||||
// capture phy state and disable lpm and suspend
|
||||
uint32_t phycfg = ugbl->gusb2phycfg0;
|
||||
ugbl->gusb2phycfg0_b.enblslpm = 0;
|
||||
ugbl->gusb2phycfg0_b.suspendusb20 = 0;
|
||||
|
||||
// set up command in depcmd register
|
||||
udev->depcmd[ep].depcmd_b.cmdtyp = typ;
|
||||
udev->depcmd[ep].depcmd_b.cmdioc = 0;
|
||||
udev->depcmd[ep].depcmd_b.commandparam = param;
|
||||
|
||||
// dispatch command and wait for completion
|
||||
udev->depcmd[ep].depcmd_b.cmdact = 1;
|
||||
while(0 != udev->depcmd[ep].depcmd_b.cmdact);
|
||||
|
||||
// restore phy state
|
||||
ugbl->gusb2phycfg0 = phycfg;
|
||||
|
||||
return udev->depcmd[ep].depcmd_b.cmdstatus;
|
||||
}
|
||||
|
||||
|
||||
static void _dcd_handle_depevt(uint8_t ep, uint8_t evt, uint8_t sts, uint16_t par)
|
||||
{
|
||||
LOG("%010u DEPEVT ep%u evt%u sts%u par%u", DWT->CYCCNT, ep, evt, sts, par);
|
||||
|
||||
switch (evt) {
|
||||
case DEPEVT_XFERCOMPLETE: {
|
||||
LOG("Transfer complete");
|
||||
RTSS_InvalidateDCache_by_Addr(_xfer_trb[ep], sizeof(_xfer_trb[0]));
|
||||
if (0 == ep) {
|
||||
uint8_t trbctl = (_xfer_trb[0][3] >> 4) & 0x3F;
|
||||
LOG("ep0 xfer trb3 = %08x", _xfer_trb[0][3]);
|
||||
if (TRBCTL_CTL_SETUP == trbctl) {
|
||||
RTSS_InvalidateDCache_by_Addr(_ctrl_buf, sizeof(_ctrl_buf));
|
||||
LOG("%02x %02x %02x %02x %02x %02x %02x %02x",
|
||||
_ctrl_buf[0], _ctrl_buf[1], _ctrl_buf[2], _ctrl_buf[3],
|
||||
_ctrl_buf[4], _ctrl_buf[5], _ctrl_buf[6], _ctrl_buf[7]);
|
||||
dcd_event_setup_received(TUD_OPT_RHPORT, _ctrl_buf, true);
|
||||
} else if (TRBCTL_CTL_STAT3 == trbctl) {
|
||||
if (0 < _xfer_bytes[0]) {
|
||||
RTSS_InvalidateDCache_by_Addr((void*) _xfer_trb[0][0], _xfer_bytes[0]);
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(0, TUSB_DIR_OUT),
|
||||
_xfer_bytes[0] - (_xfer_trb[0][2] & 0xFFFFFF),
|
||||
XFER_RESULT_SUCCESS, true);
|
||||
} else {
|
||||
if (2 == ++_sts_stage) {
|
||||
_sts_stage = 0;
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(0, TUSB_DIR_OUT),
|
||||
0, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
// *(volatile uint32_t*) 0x4900C000 ^= 8; // [TEMP]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// invalid TRBCTL value
|
||||
__BKPT(0);
|
||||
}
|
||||
} else if (1 == ep) {
|
||||
uint8_t trbctl = (_xfer_trb[1][3] >> 4) & 0x3F;
|
||||
LOG("ep1 xfer trb3 = %08x trb2 = %08x", _xfer_trb[1][3], _xfer_trb[1][2]);
|
||||
if (TRBCTL_CTL_STAT2 != trbctl) { // STATUS IN notification is done at xfer request
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(0, TUSB_DIR_IN),
|
||||
_xfer_bytes[1] - (_xfer_trb[1][2] & 0xFFFFFF),
|
||||
XFER_RESULT_SUCCESS, true);
|
||||
} else {
|
||||
if (2 == ++_sts_stage) {
|
||||
_sts_stage = 0;
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(0, TUSB_DIR_IN),
|
||||
0, XFER_RESULT_SUCCESS, true);
|
||||
|
||||
// *(volatile uint32_t*) 0x4900C000 ^= 8; // [TEMP]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// [TODO] check if ep is open
|
||||
LOG("ep%u xfer trb3 = %08x trb2 = %08x", ep, _xfer_trb[ep][3], _xfer_trb[ep][2]);
|
||||
if (TUSB_DIR_OUT == tu_edpt_dir(tu_edpt_addr(ep >> 1, ep & 1))) {
|
||||
RTSS_InvalidateDCache_by_Addr((void*) _xfer_trb[ep][0],
|
||||
512 - _xfer_trb[ep][2]);
|
||||
// _xfer_bytes[ep] - _xfer_trb[ep][2]);
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(ep >> 1, ep & 1),
|
||||
512 - _xfer_trb[ep][2],
|
||||
XFER_RESULT_SUCCESS, true);
|
||||
} else
|
||||
dcd_event_xfer_complete(TUD_OPT_RHPORT, tu_edpt_addr(ep >> 1, ep & 1),
|
||||
_xfer_bytes[ep] - _xfer_trb[ep][2],
|
||||
XFER_RESULT_SUCCESS, true);
|
||||
}
|
||||
} break;
|
||||
case DEPEVT_XFERINPROGRESS: {
|
||||
LOG("Transfer in progress");
|
||||
} break;
|
||||
case DEPEVT_XFERNOTREADY: {
|
||||
LOG("Transfer not ready: %s", sts & 8 ? "no TRB" : "no XFER");
|
||||
|
||||
// XferNotReady NotActive for status stage
|
||||
if ((1 == ep) && (0b0010 == (sts & 0b1011))) {
|
||||
_dcd_start_xfer(1, NULL, 0, TRBCTL_CTL_STAT2);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((0 == ep) && (0b0010 == (sts & 0b1011))) {
|
||||
_xfer_bytes[0] = 0;
|
||||
_dcd_start_xfer(0, _ctrl_buf, 64, TRBCTL_CTL_STAT3);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((1 > ep) && (sts & (1 << 3))) {
|
||||
if (_xfer_trb[ep][3] & (1 << 0)) { // transfer was configured
|
||||
// dependxfer can only block when actbitlater is set
|
||||
ugbl->guctl2_b.rst_actbitlater = 1;
|
||||
_dcd_cmd_wait(ep, CMDTYP_DEPENDXFER, 0);
|
||||
ugbl->guctl2_b.rst_actbitlater = 0;
|
||||
|
||||
// reset the trb byte count and clean the cache
|
||||
RTSS_InvalidateDCache_by_Addr(_xfer_trb[ep], sizeof(_xfer_trb[0]));
|
||||
_xfer_trb[ep][2] = _xfer_bytes[ep];
|
||||
RTSS_CleanDCache_by_Addr(_xfer_trb[ep], sizeof(_xfer_trb[ep]));
|
||||
|
||||
// prepare ep command
|
||||
udev->depcmd[ep].par1 = (uint32_t) LocalToGlobal(_xfer_trb[ep]);
|
||||
udev->depcmd[ep].par0 = 0;
|
||||
|
||||
// issue the block command and pass the status
|
||||
_dcd_cmd_wait(ep, CMDTYP_DEPSTRTXFER, 0);
|
||||
|
||||
*(volatile uint32_t*) 0x49007000 ^= 16; // [TEMP]
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case DEPEVT_EPCMDCMPLT: {
|
||||
// redundant, currently no commands are issued with IOC bit set
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _dcd_handle_devt(uint8_t evt, uint16_t info)
|
||||
{
|
||||
LOG("%010u DEVT evt%u info%u", DWT->CYCCNT, evt, info);
|
||||
switch (evt) {
|
||||
case DEVT_USBRST: {
|
||||
_xfer_cfgd = false;
|
||||
|
||||
// [TODO] issue depcstall for any ep in stall mode
|
||||
udev->dcfg_b.devaddr = 0;
|
||||
LOG("USB reset");
|
||||
dcd_event_bus_reset(TUD_OPT_RHPORT, TUSB_SPEED_HIGH, true); // [TODO] actual speed
|
||||
} break;
|
||||
case DEVT_CONNECTDONE: {
|
||||
// read conn speed from dsts
|
||||
// program ramclksel in gctl if needed
|
||||
LOG("Connect done");
|
||||
|
||||
udev->depcmd[0].par1 = (0 << 25) | (1 << 10) | (1 << 8);
|
||||
udev->depcmd[0].par0 = (2 << 30) | (0 << 22) | (0 << 17) | (64 << 3) | (0 << 1);
|
||||
_dcd_cmd_wait(0, CMDTYP_DEPCFG, 0);
|
||||
|
||||
udev->depcmd[1].par1 = (1 << 25) | (1 << 10) | (1 << 8);
|
||||
udev->depcmd[1].par0 = (2 << 30) | (0 << 22) | (0 << 17) | (64 << 3) | (0 << 1);
|
||||
_dcd_cmd_wait(1, CMDTYP_DEPCFG, 0);
|
||||
} break;
|
||||
case DEVT_ULSTCHNG: {
|
||||
LOG("Link status change");
|
||||
switch (info) {
|
||||
case 0x3: { // suspend (L2)
|
||||
dcd_event_bus_signal(TUD_OPT_RHPORT, DCD_EVENT_SUSPEND, true);
|
||||
} break;
|
||||
case 0x4: { // disconnected
|
||||
dcd_event_bus_signal(TUD_OPT_RHPORT, DCD_EVENT_UNPLUGGED, true);
|
||||
} break;
|
||||
case 0xF: { // resume
|
||||
dcd_event_bus_signal(TUD_OPT_RHPORT, DCD_EVENT_RESUME, true);
|
||||
} break;
|
||||
default: {}
|
||||
}
|
||||
// 0x0: ON state
|
||||
// 0x2: L1 state (sleep)
|
||||
// 0x3: L2 state (suspend)
|
||||
// 0x4: disconnected state
|
||||
// 0x5: early suspend
|
||||
// 0xE: reset
|
||||
// 0xF: resume
|
||||
} break;
|
||||
case DEVT_ERRTICERR: {
|
||||
__BKPT(0);
|
||||
} break;
|
||||
default: {
|
||||
LOG("Unknown DEVT event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static uint8_t _dcd_start_xfer(uint8_t ep, void* buf, uint32_t size, uint8_t type)
|
||||
{
|
||||
dcd_int_disable(TUD_OPT_RHPORT); // prevent race conditions
|
||||
|
||||
// program the trb and clean the cache
|
||||
_xfer_trb[ep][0] = buf ? (uint32_t) LocalToGlobal(buf) : 0;
|
||||
_xfer_trb[ep][1] = 0;
|
||||
_xfer_trb[ep][2] = size;
|
||||
_xfer_trb[ep][3] = (1 << 11) | (1 << 10) | (type << 4) | (1 << 1) | (1 << 0);
|
||||
RTSS_CleanDCache_by_Addr(_xfer_trb[ep], sizeof(_xfer_trb[ep]));
|
||||
|
||||
// prepare ep command
|
||||
udev->depcmd[ep].par1 = (uint32_t) LocalToGlobal(_xfer_trb[ep]);
|
||||
udev->depcmd[ep].par0 = 0;
|
||||
|
||||
dcd_int_enable(TUD_OPT_RHPORT);
|
||||
|
||||
// issue the block command and pass the status
|
||||
return _dcd_cmd_wait(ep, CMDTYP_DEPSTRTXFER, 0);
|
||||
}
|
||||
|
||||
#endif // CFG_TUD_ENABLED
|
||||
Reference in New Issue
Block a user