Comparar commits
7 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| f48cef3768 | |||
| cd8fd74356 | |||
| 819f8ab8c4 | |||
| 937a808501 | |||
| c2a4304217 | |||
| 72efa255f4 | |||
| acce76482c |
@@ -117,4 +117,46 @@ platform = {
|
||||
}
|
||||
}
|
||||
}
|
||||
device = {
|
||||
name = "hi3660-dwc3"
|
||||
did = 1
|
||||
mmios = {
|
||||
{
|
||||
name = "USB3OTG"
|
||||
base-phys = 0xff100000
|
||||
length = 0x100000
|
||||
}
|
||||
{
|
||||
name = "USB3OTG_BC"
|
||||
base-phys = 0xff200000
|
||||
length = 0x1000
|
||||
}
|
||||
// TODO(voydanoff) the remaining MMIO ranges should move to the bus node
|
||||
// since they will likely be used by drivers for other devices
|
||||
{
|
||||
name = "PERI_CRG"
|
||||
base-phys = 0xfff35000
|
||||
length = 0x1000
|
||||
}
|
||||
{
|
||||
name = "PCTRL"
|
||||
base-phys = 0xe8a09000
|
||||
length = 0x1000
|
||||
}
|
||||
{
|
||||
name = "SCTRL"
|
||||
base-phys = 0xfff0a000
|
||||
length = 0x1000
|
||||
}
|
||||
{
|
||||
name = "PMCTRL"
|
||||
base-phys = 0xfff31000
|
||||
length = 0x1000
|
||||
}
|
||||
}
|
||||
irqs = [ 191 /* USB3 */,
|
||||
193 /* USB3_OTG */,
|
||||
194 /* USB3_BC */,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
// Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
|
||||
#include <hw/reg.h>
|
||||
|
||||
#define DWC3_READ32(a) readl(a)
|
||||
#define DWC3_WRITE32(a, v) writel(v, a)
|
||||
#define DWC3_READ64(a) readll(a)
|
||||
#define DWC3_WRITE64(a, v) writell(v, a)
|
||||
|
||||
#define DWC3_SET32(addr, mask, bits) DWC3_WRITE32(addr, (DWC3_READ32(addr) & ~(mask)) | ((bits) & (mask)))
|
||||
|
||||
#define DWC3_MASK(start, count) (((1 << (count)) - 1) << (start))
|
||||
#define DWC3_GET_BITS32(src, start, count) ((DWC3_READ32(src) & DWC3_MASK(start, count)) >> (start))
|
||||
#define DWC3_SET_BITS32(dest, start, count, value) \
|
||||
DWC3_WRITE32(dest, (DWC3_READ32(dest) & ~DWC3_MASK(start, count)) | \
|
||||
(((value) << (start)) & DWC3_MASK(start, count)))
|
||||
|
||||
// XHCI register offsets
|
||||
#define CAPLENGTH 0x0000 // Capability Registers Length Host Controller Operational Registers
|
||||
#define CAPLENGTH_HCIVERSION_START 16
|
||||
#define CAPLENGTH_HCIVERSION_BITS 16
|
||||
#define CAPLENGTH_CAPLENGTH_START 0
|
||||
#define CAPLENGTH_CAPLENGTH_BITS 8
|
||||
|
||||
#define HCSPARAMS1 0x0004 // Structural Parameters 1 Register
|
||||
#define HCSPARAMS1_MAXPORTS_START 24
|
||||
#define HCSPARAMS1_MAXPORTS_BITS 8
|
||||
#define HCSPARAMS1_MAXINTRS_START 8
|
||||
#define HCSPARAMS1_MAXINTRS_BITS 11
|
||||
#define HCSPARAMS1_MAXSLOTS_START 0
|
||||
#define HCSPARAMS1_MAXSLOTS_BITS 8
|
||||
|
||||
#define HCSPARAMS2 0x0008 // Structural Parameters 2 Register
|
||||
#define HCSPARAMS2_MAXSCRATCHPADBUFS_START 27
|
||||
#define HCSPARAMS2_MAXSCRATCHPADBUFS_BITS 5
|
||||
#define HCSPARAMS2_SPR (1 << 26)
|
||||
#define HCSPARAMS2_MAXSCRATCHPADBUFS_HI_START 21
|
||||
#define HCSPARAMS2_MAXSCRATCHPADBUFS_HI_BITS 5
|
||||
#define HCSPARAMS2_ERSTMAX_START 4
|
||||
#define HCSPARAMS2_ERSTMAX_BITS 4
|
||||
#define HCSPARAMS2_IST_START 0
|
||||
#define HCSPARAMS2_IST_BITS 4
|
||||
|
||||
#define HCSPARAMS3 0x000c // Structural Parameters 3 Register
|
||||
#define HCSPARAMS3_U2_DEVICE_EXIT_LAT_START 16
|
||||
#define HCSPARAMS3_U2_DEVICE_EXIT_LAT_BITS 16
|
||||
#define HCSPARAMS3_U1_DEVICE_EXIT_LAT_START 0
|
||||
#define HCSPARAMS3_U1_DEVICE_EXIT_LAT_BITS 8
|
||||
|
||||
#define HCCPARAMS1 0x0010 // Capability Parameters 1 Register
|
||||
#define HCCPARAMS1_XECP_START 16
|
||||
#define HCCPARAMS1_XECP_BITS 16
|
||||
#define HCCPARAMS1_MAXPSASIZE_START 12
|
||||
#define HCCPARAMS1_MAXPSASIZE_BITS 4
|
||||
#define HCCPARAMS1_CFC (1 << 11)
|
||||
#define HCCPARAMS1_SEC (1 << 10)
|
||||
#define HCCPARAMS1_SPC (1 << 9)
|
||||
#define HCCPARAMS1_PAE (1 << 8)
|
||||
#define HCCPARAMS1_NSS (1 << 7)
|
||||
#define HCCPARAMS1_LTC (1 << 6)
|
||||
#define HCCPARAMS1_LHRC (1 << 5)
|
||||
#define HCCPARAMS1_PIND (1 << 4)
|
||||
#define HCCPARAMS1_PPC (1 << 3)
|
||||
#define HCCPARAMS1_CSZ (1 << 2)
|
||||
#define HCCPARAMS1_BNC (1 << 1)
|
||||
#define HCCPARAMS1_AC64 (1 << 0)
|
||||
|
||||
#define DBOFF 0x0014 // Doorbell Offset Register
|
||||
#define RTSOFF 0x0018 // Runtime Register Space Offset Register
|
||||
|
||||
#define HCCPARAMS2 0x001c // Host Controller Capability Parameters 2
|
||||
#define HCCPARAMS2_ETC (1 << 6)
|
||||
#define HCCPARAMS2_CIC (1 << 5)
|
||||
#define HCCPARAMS2_LEC (1 << 4)
|
||||
#define HCCPARAMS2_CTC (1 << 3)
|
||||
#define HCCPARAMS2_FSC (1 << 2)
|
||||
#define HCCPARAMS2_CMC (1 << 1)
|
||||
#define HCCPARAMS2_U3C (1 << 0)
|
||||
|
||||
// Global register offsets
|
||||
#define GSBUSCFG0 0xc100 // Global SoC Bus Configuration Register 0
|
||||
#define GSBUSCFG1 0xc104 // Global SoC Bus Configuration Register 1
|
||||
#define GTXTHRCFG 0xc108 // Global Tx Threshold Control Register
|
||||
#define GRXTHRCFG 0xc10c // Global Rx Threshold Control Register
|
||||
|
||||
#define GCTL 0xc110 // Global Core Control Register
|
||||
#define GCTL_PWRDNSCALE_START 19
|
||||
#define GCTL_PWRDNSCALE_BITS 13
|
||||
#define GCTL_MASTERFILTBYPASS (1 << 18)
|
||||
#define GCTL_BYPSSETADDR (1 << 17)
|
||||
#define GCTL_U2RSTECN (1 << 16)
|
||||
#define GCTL_FRMSCLDWN_START 14
|
||||
#define GCTL_FRMSCLDWN_BITS 2
|
||||
#define GCTL_PRTCAPDIR_START 12
|
||||
#define GCTL_PRTCAPDIR_BITS 2
|
||||
#define GCTL_PRTCAPDIR_HOST (1 << GCTL_PRTCAPDIR_START)
|
||||
#define GCTL_PRTCAPDIR_DEVICE (2 << GCTL_PRTCAPDIR_START)
|
||||
#define GCTL_PRTCAPDIR_OTG (3 << GCTL_PRTCAPDIR_START)
|
||||
#define GCTL_PRTCAPDIR_MASK (3 << GCTL_PRTCAPDIR_START)
|
||||
#define GCTL_CORESOFTRESET (1 << 11)
|
||||
#define GCTL_U1_U2_TIMER_SCALE (1 << 9)
|
||||
#define GCTL_DEBUGATTACH (1 << 8)
|
||||
#define GCTL_SCALEDOWN_START 4
|
||||
#define GCTL_SCALEDOWN_BITS 2
|
||||
#define GCTL_DISSCRAMBLE (1 << 3)
|
||||
#define GCTL_U2EXIT_LFPS (1 << 2)
|
||||
#define GCTL_GBL_HIBERNATION_EN (1 << 1)
|
||||
#define GCTL_DSBLCLKGTNG (1 << 0)
|
||||
|
||||
#define GPMSTS 0xc114 // Global Power Management Status Register
|
||||
#define GSTS 0xc118 // Global Status Register
|
||||
#define GUCTL1 0xc11c // Global User Control Register 1
|
||||
#define USB31_IP_NAME 0xc120 // IP NAME REGISTER
|
||||
#define GGPIO 0xc124 // Global General Purpose Input/Output Register
|
||||
#define GUID 0xc128 // Global User ID Register
|
||||
#define GUCTL 0xc12c // Global User Control Register
|
||||
#define GBUSERRADDR 0xc130 // Global Soc Bus Error Address Register
|
||||
#define GBUSERRADDRLO 0xc130 // Global Soc Bus Error Address Register - Low
|
||||
#define GBUSERRADDRHI 0xc134 // Global Soc Bus Error Address Register - High
|
||||
#define GPRTBIMAP 0xc138 // Global SS Port to Bus Instance Mapping Register - Low
|
||||
#define GPRTBIMAPHI 0xc13c // Global SS Port to Bus Instance Mapping Register - High
|
||||
#define GHWPARAMS0 0xc140 // Global Hardware Parameters Register 0
|
||||
#define GHWPARAMS1 0xc144 // Global Hardware Parameters Register 1
|
||||
#define GHWPARAMS2 0xc148 // Global Hardware Parameters Register 2
|
||||
#define GHWPARAMS3 0xc14c // Global Hardware Parameters Register 3
|
||||
#define GHWPARAMS4 0xc150 // Global Hardware Parameters Register 4
|
||||
#define GHWPARAMS5 0xc154 // Global Hardware Parameters Register 5
|
||||
#define GHWPARAMS6 0xc158 // Global Hardware Parameters Register 6
|
||||
#define GHWPARAMS7 0xc15c // Global Hardware Parameters Register 7
|
||||
#define GDBGFIFOSPACE 0xc160 // Global Debug Queue/FIFO Space Available Register
|
||||
#define GBMUCTL 0xc164 // Global BMU Control Register
|
||||
#define GDBGBMU 0xc16c // Global Debug BMU Register
|
||||
#define GDBGLSPMUX_HST 0xc170 // Global Debug LSP MUX Register in host mode
|
||||
#define GDBGLSPMUX_DEV 0xc170 // Global Debug LSP MUX Register
|
||||
#define GDBGLSP 0xc174 // Global Debug LSP Register
|
||||
#define GDBGEPINFO0 0xc178 // Global Debug Endpoint Information Register 0
|
||||
#define GDBGEPINFO1 0xc17c // Global Debug Endpoint Information Register 1
|
||||
#define GPRTBIMAP_HS 0xc180 // Global High-Speed Port to Bus Instance Mapping Register
|
||||
#define GPRTBIMAP_HSLO 0xc180 // Global High-Speed Port to Bus Instance Mapping Register - Low
|
||||
#define GPRTBIMAP_HSHI 0xc184 // Global High-Speed Port to Bus Instance Mapping Register - High
|
||||
#define GPRTBIMAP_FS 0xc188 // Global Full/Low-Speed Port to Bus Instance Mapping Register
|
||||
#define GPRTBIMAP_FSLO 0xc188 // Global Full/Low-Speed Port to Bus Instance Mapping Register - Low
|
||||
#define GPRTBIMAP_FSHI 0xc18c // Global Full/Low-Speed Port to Bus Instance Mapping Register - High
|
||||
#define GHMSOCBWOR 0xc190 // Global Host Mode SoC Bandwidth Override Register
|
||||
#define GERRINJCTL_1 0xc194 // Global Error Injection 1 Control Register
|
||||
#define GERRINJCTL_2 0xc194 // Global Error Injection 2 Control Register
|
||||
#define USB31_VER_NUMBER 0xc1a0 // USB31 IP VERSION NUMBER
|
||||
#define USB31_VER_TYPE 0xc1a4 // USB31 IP VERSION TYPE
|
||||
#define GSYSBLKWINCTRL 0xc1b0 // System Bus Blocking Window Control
|
||||
//#defineGUSB3RMMICTL(n) varies
|
||||
#define GUSB2PHYCFG(n) (0xc200 + 4 * (n)) // Global USB2 PHY Configuration Register
|
||||
#define GUSB2I2CCTL(n) (0xc240 + 4 * (n)) // Reserved Register
|
||||
#define GUSB2PHYACC_UTMI(n) (0xc280 + 4 * (n)) // Global USB 2.0 UTMI PHY Vendor Control Register
|
||||
#define GUSB2PHYACC_ULPI(n) (0xc280 + 4 * (n)) // Global USB 2.0 UTMI PHY Vendor Control Register
|
||||
#define GUSB3PIPECTL(n) (0xc2c0 + 4 * (n)) // Global USB 3.1 PIPE Control Register
|
||||
#define GTXFIFOSIZ(n) (0xc300 + 0x7c * (n)) // Global Transmit FIFO Size Register
|
||||
#define GRXFIFOSIZ(n) (0xc380 + 0x7c * (n)) // Global Receive FIFO Size Register
|
||||
#define GEVNTADR(n) (0xc400 + 0x10 * (n)) // Global Event Buffer Address Register
|
||||
#define GEVNTADRLO(n) (0xc400 + 0x10 * (n)) // Global Event Buffer Address Register - Low
|
||||
#define GEVNTADRHI(n) (0xc404 + 0x10 * (n)) // Global Event Buffer Address Register - High
|
||||
#define GEVNTSIZ(n) (0xc408 + 0x10 * (n)) // Global Event Buffer Size Register
|
||||
#define GEVNTCOUNT(n) (0xc408 + 0x10 * (n)) // Global Event Buffer Size Register
|
||||
#define GHWPARAMS8 0xc600 // Global Hardware Parameters Register 8
|
||||
#define GSMACCTL 0xc604 // Global SMAC CONTROL REGISTER
|
||||
#define GUCTL2 0xc608 // Global User Control Register 2
|
||||
#define GUCTL3 0xc60c // Global User Control Register 3
|
||||
#define GTXFIFOPRIDEV 0xc610 // Global Device TXFIFO DMA Priority Register
|
||||
#define GTXFIFOPRIHST 0xc618 // Global Host TXFIFO DMA Priority Register
|
||||
#define GRXFIFOPRIHST 0xc61c // Global Host RXFIFO DMA Priority Register
|
||||
#define GFIFOPRIDBC 0xc620 // Global Host Debug Capability DMA Priority Register
|
||||
#define GDMAHLRATIO 0xc624 // Global Host FIFO DMA High-Low Priority Ratio Register
|
||||
#define GOSTDDMA_ASYNC 0xc628 // Global Number of Async Outstanding DMA Register
|
||||
#define GOSTDDMA_PRD 0xc62c // Global Number of Periodic Outstanding DMA Register
|
||||
#define GFLADJ 0xc630 // Global Frame Length Adjustment Register
|
||||
#define GUSB2RHBCTL(n) (0xc640 + 4 * (n)) // Global USB2 PHY Configuration Register
|
||||
|
||||
// Device mode register offsets
|
||||
#define DCFG 0xc700 // Device Configuration Register
|
||||
#define DCFG_STOP_ON_DISCONNECT (1 << 24)
|
||||
#define DCFG_IGN_STRM_PP (1 << 23)
|
||||
#define DCFG_LPMCAP (1 << 22)
|
||||
#define DCFG_NUMP_START 17
|
||||
#define DCFG_NUMP_BITS 5
|
||||
#define DCFG_INTRNUM_START 12
|
||||
#define DCFG_INTRNUM_BITS 5
|
||||
#define DCFG_DEVADDR_START 3
|
||||
#define DCFG_DEVADDR_BITS 7
|
||||
#define DCFG_DEVSPD_START 0
|
||||
#define DCFG_DEVSPD_BITS 3
|
||||
|
||||
#define DCTL 0xc704 // Device Control Register
|
||||
#define DCTL_RUN_STOP (1 << 31)
|
||||
#define DCTL_CSFTRST (1 << 30)
|
||||
#define DCFG_HIRDTHRES_START 24
|
||||
#define DCFG_HIRDTHRES_BITS 5
|
||||
#define DCFG_LPM_NYET_THRES_START 20
|
||||
#define DCFG_LPM_NYET_THRES_BITS 4
|
||||
#define DCTL_KEEP_CONNECT (1 << 19)
|
||||
#define DCTL_L1_HIBERNATION_EN (1 << 18)
|
||||
#define DCTL_CRS (1 << 17)
|
||||
#define DCTL_CSS (1 << 16)
|
||||
#define DCTL_INITU2ENA (1 << 12)
|
||||
#define DCTL_ACCEPTU2ENA (1 << 11)
|
||||
#define DCTL_INITU1ENA (1 << 10)
|
||||
#define DCTL_ACCEPTU1ENA (1 << 9)
|
||||
#define DCTL_ACCEPTU1ENA (1 << 9)
|
||||
#define DCFG_ULSTCHNGREQ_START 5
|
||||
#define DCFG_ULSTCHNGREQ_BITS 4
|
||||
#define DCFG_TSTCTL_START 1
|
||||
#define DCFG_TSTCTL_BITS 4
|
||||
|
||||
#define DEVTEN 0xc708 // Device Event Enable Register
|
||||
#define DEVTEN_LDMEVTEN (1 << 15)
|
||||
#define DEVTEN_L1WKUPEVTEN (1 << 14)
|
||||
#define DEVTEN_STOP_ON_DISCONNECT_EN (1 << 13)
|
||||
#define DEVTEN_VENDEVTSTRCVDEN (1 << 12)
|
||||
#define DEVTEN_ERRTICERREVTEN (1 << 9)
|
||||
#define DEVTEN_L1SUSPEN (1 << 8)
|
||||
#define DEVTEN_SOFTEVTEN (1 << 7)
|
||||
#define DEVTEN_U3_L2_SUSP_EN (1 << 6)
|
||||
#define DEVTEN_HIBERNATION_REQ_EVT_EN (1 << 5)
|
||||
#define DEVTEN_WKUPEVTEN (1 << 4)
|
||||
#define DEVTEN_ULSTCNGEN (1 << 3)
|
||||
#define DEVTEN_CONNECTDONEEVTEN (1 << 2)
|
||||
#define DEVTEN_USBRSTEVTEN (1 << 1)
|
||||
#define DEVTEN_DISSCONNEVTEN (1 << 0)
|
||||
|
||||
#define DSTS 0xc70c // Device Status Register
|
||||
|
||||
#define DSTS_DCNRD (1 << 29)
|
||||
#define DSTS_SRE (1 << 28)
|
||||
#define DSTS_RSS (1 << 25)
|
||||
#define DSTS_SSS (1 << 24)
|
||||
#define DSTS_COREIDLE (1 << 23)
|
||||
#define DSTS_DEVCTRLHLT (1 << 22)
|
||||
#define DCFG_USBLNKST_START 18
|
||||
#define DCFG_USBLNKST_BITS 4
|
||||
#define DSTS_RXFIFOEMPTY (1 << 17)
|
||||
#define DCFG_SOFFN_START 3
|
||||
#define DCFG_SOFFN_BITS 14
|
||||
#define DCFG_CONNECTSPD_START 0
|
||||
#define DCFG_CONNECTSPD_BITS 3
|
||||
|
||||
#define DGCMDPAR 0xc710 // Device Generic Command Parameter Register
|
||||
#define DGCMD 0xc714 // Device Generic Command Register
|
||||
#define DGCMD_CMDSTATUS_START 12
|
||||
#define DGCMD_CMDSTATUS_BITS 4
|
||||
#define DGCMD_CMDACT (1 << 10)
|
||||
#define DGCMD_CMDIOC (1 << 8)
|
||||
#define DGCMD_CMDTYP_START 0
|
||||
#define DGCMD_CMDTYP_BITS 8
|
||||
|
||||
#define DALEPENA 0xc720 // Device Active USB Endpoint Enable Register
|
||||
#define DLDMENA 0xc724 // Device LDM Request Control Register
|
||||
|
||||
#define DEPCMDPAR2(n) (0xc800 + 0x10 * (n)) // Device Physical Endpoint-n Command Parameter 2 Register
|
||||
#define DEPCMDPAR1(n) (0xc804 + 0x10 * (n)) // Device Physical Endpoint-n Command Parameter 1 Register
|
||||
#define DEPCMDPAR0(n) (0xc808 + 0x10 * (n)) // Device Physical Endpoint-n Command Parameter 0 Register
|
||||
#define DEPCMD(n) (0xc80c + 0x10 * (n)) // Device Physical Endpoint-n Command Parameter 0 Register
|
||||
#define DEV_IMOD(n) (0xca00 + 4 * (n)) // Device Interrupt Moderation Register
|
||||
|
||||
// BC register offsets
|
||||
#define BCFG 0xcc30 // BC Configuration Register
|
||||
#define BCEVT 0xcc38 // BC Event Register
|
||||
#define BCEVTEN 0xcc3c // BC Event Enable Register
|
||||
|
||||
// Link register offsets
|
||||
#define LU1LFPSRXTIM(n) (0xd000 + 0x80 * (n)) // U1_LFPS_RX_TIMER_REG
|
||||
#define LU1LFPSTXTIM(n) (0xd004 + 0x80 * (n)) // U1 LFPS TX TIMER REGISTER
|
||||
#define LU2LFPSRXTIM(n) (0xd008 + 0x80 * (n)) // U1 LFPS RX TIMER REGISTER
|
||||
#define LU2LFPSTXTIM(n) (0xd00c + 0x80 * (n)) // U2 LFPS TX TIMER REG REGISTER
|
||||
#define LU3LFPSRXTIM(n) (0xd010 + 0x80 * (n)) // U3 LFPS RX TIMER REGS REGISTER
|
||||
#define LU3LFPSTXTIM(n) (0xd014 + 0x80 * (n)) // U3 LFPS TX TIMER REGS REGISTER
|
||||
#define LPINGLFPSTIM(n) (0xd018 + 0x80 * (n)) // PING LFPS TIMER REGISTER
|
||||
#define LPOLLLFPSTXTIM(n) (0xd01c + 0x80 * (n)) // POLL LFPS TX TIMER REGISTER
|
||||
#define LSKIPFREQ(n) (0xd020 + 0x80 * (n)) // SKIP FREQUENCY REGISTER
|
||||
#define LLUCTL(n) (0xd024 + 0x80 * (n)) // TX TS1 COUNT REGISTER
|
||||
#define LPTMDPDELAY(n) (0xd028 + 0x80 * (n)) // PTM DATAPATH DELAY REGISTER
|
||||
#define LSCDTIM1(n) (0xd02c + 0x80 * (n)) // SCD TIMER 1 REGISTER
|
||||
#define LSCDTIM2(n) (0xd030 + 0x80 * (n)) // SCD TIMER 2 REGISTER
|
||||
#define LSCDTIM3(n) (0xd034 + 0x80 * (n)) // SCD TIMER 3 REGISTER
|
||||
#define LSCDTIM4(n) (0xd038 + 0x80 * (n)) // SCD TIMER 4 REGISTER
|
||||
#define LLPBMTIM1(n) (0xd03c + 0x80 * (n)) // LPBM TIMER 1 REGISTER
|
||||
#define LLPBMTIM2(n) (0xd040 + 0x80 * (n)) // LPBM TIMER 2 REGISTER
|
||||
#define LLPBMTXTIM(n) (0xd044 + 0x80 * (n)) // LPBM TX TIMER REGISTER
|
||||
#define LLINKERRINJ(n) (0xd048 + 0x80 * (n)) // LINK ERROR TYPE INJECT REGISTER
|
||||
#define LLINKERRINJEN(n) (0xd04c + 0x80 * (n)) // LINK ERROR INJECT ENABLE REGISTER
|
||||
#define GDBGLTSSM(n) (0xd050 + 0x80 * (n)) // Global Debug LTSSM Register
|
||||
#define GDBGLNMCC(n) (0xd054 + 0x80 * (n)) // Global Debug LNMCC Register
|
||||
#define LLINKDBGCTRL(n) (0xd058 + 0x80 * (n)) // LINK DEBUG CONTROL REGISTER
|
||||
#define LLINKDBGCNTTRIG(n) (0xd05c + 0x80 * (n)) // LINK DEBUG COUNT TRIGGER REGISTER
|
||||
#define LCSR_TX_DEEMPH(n) (0xd060 + 0x80 * (n)) // LCSR_TX_DEEMPH REGISTER
|
||||
#define LCSR_TX_DEEMPH_1(n) (0xd064 + 0x80 * (n)) // LCSR_TX_DEEMPH_1 REGISTER
|
||||
#define LCSR_TX_DEEMPH_2(n) (0xd068 + 0x80 * (n)) // LCSR_TX_DEEMPH_2 REGISTER
|
||||
#define LCSR_TX_DEEMPH_3(n) (0xd06c + 0x80 * (n)) // LCSR_TX_DEEMPH_3 REGISTER
|
||||
#define LCSRPTMDEBUG1(n) (0xd070 + 0x80 * (n)) // LCSRPTMDEBUG1 REGISTER
|
||||
#define LCSRPTMDEBUG2(n) (0xd074 + 0x80 * (n)) // LCSRPTMDELAY2 REGISTER
|
||||
|
||||
@@ -0,0 +1,265 @@
|
||||
// Copyright 2017 The Fuchsia Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <ddk/binding.h>
|
||||
#include <ddk/device.h>
|
||||
#include <ddk/protocol/platform-device.h>
|
||||
#include <ddk/protocol/usb-xhci.h>
|
||||
#include <hw/reg.h>
|
||||
#include <pretty/hexdump.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "dwc3-regs.h"
|
||||
#include "hi3660-regs.h"
|
||||
|
||||
// MMIO indices
|
||||
enum {
|
||||
MMIO_USB3OTG,
|
||||
MMIO_USB3OTG_BC,
|
||||
MMIO_PERI_CRG,
|
||||
MMIO_PCTRL,
|
||||
MMIO_SCTRL,
|
||||
MMIO_PMCTRL,
|
||||
};
|
||||
|
||||
// IRQ indices
|
||||
enum {
|
||||
IRQ_USB3,
|
||||
IRQ_USB3_OTG,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
mx_device_t* mxdev;
|
||||
platform_device_protocol_t pdev;
|
||||
pdev_mmio_buffer_t usb3otg;
|
||||
pdev_mmio_buffer_t usb3otg_bc;
|
||||
pdev_mmio_buffer_t peri_crg;
|
||||
pdev_mmio_buffer_t pctrl;
|
||||
pdev_mmio_buffer_t sctrl;
|
||||
pdev_mmio_buffer_t pmctrl;
|
||||
} hi3360_dwc3_t;
|
||||
|
||||
|
||||
static mx_status_t hi3360_dwc3_init(hi3360_dwc3_t* dwc) {
|
||||
|
||||
volatile void* usb3otg_bc = dwc->usb3otg_bc.vaddr;
|
||||
volatile void* peri_crg = dwc->peri_crg.vaddr;
|
||||
volatile void* pctrl = dwc->pctrl.vaddr;
|
||||
|
||||
writel(PERRSTEN4_USB3OTG, peri_crg + PERI_CRG_PERRSTEN4);
|
||||
writel(PERRSTEN4_USB3OTGPHY_POR, peri_crg + PERI_CRG_PERRSTEN4);
|
||||
writel(PERRSTEN4_USB3OTG_MUX | PERRSTEN4_USB3OTG_AHBIF | PERRSTEN4_USB3OTG_32K, peri_crg + PERI_CRG_PERRSTEN4);
|
||||
writel(PEREN4_GT_ACLK_USB3OTG | PEREN4_GT_CLK_USB3OTG_REF, peri_crg + PERI_CRG_PERDIS4);
|
||||
|
||||
writel(~PCTRL_CTRL24_USB3PHY_3MUX1_SEL, pctrl + PCTRL_CTRL24);
|
||||
writel((PCTRL_CTRL3_USB_TXCO_EN << 16) | 0, pctrl + PCTRL_CTRL3);
|
||||
|
||||
mx_nanosleep(mx_deadline_after(MX_MSEC(10)));
|
||||
|
||||
// release part
|
||||
mx_nanosleep(mx_deadline_after(MX_MSEC(10)));
|
||||
|
||||
/* enable USB REFCLK ISO */
|
||||
writel(PERISOEN_USB_REFCLK_ISO_EN, peri_crg + PERI_CRG_ISODIS);
|
||||
|
||||
/* enable USB_TXCO_EN */
|
||||
writel((PCTRL_CTRL3_USB_TXCO_EN << 16) | PCTRL_CTRL3_USB_TXCO_EN, pctrl + PCTRL_CTRL3);
|
||||
|
||||
writel(~PCTRL_CTRL24_USB3PHY_3MUX1_SEL, pctrl + PCTRL_CTRL24);
|
||||
writel(PEREN4_GT_ACLK_USB3OTG | PEREN4_GT_CLK_USB3OTG_REF, peri_crg + PERI_CRG_PEREN4);
|
||||
writel(PERRSTEN4_USB3OTG_MUX | PERRSTEN4_USB3OTG_AHBIF | PERRSTEN4_USB3OTG_32K, peri_crg + PERI_CRG_PERRSTDIS4);
|
||||
|
||||
writel(PERRSTEN4_USB3OTG | PERRSTEN4_USB3OTGPHY_POR, peri_crg + PERI_CRG_PERRSTEN4);
|
||||
|
||||
|
||||
/* enable PHY REF CLK */
|
||||
uint32_t temp = readl(usb3otg_bc + USBOTG3_CTRL0);
|
||||
writel(temp | USB3OTG_CTRL0_SC_USB3PHY_ABB_GT_EN, usb3otg_bc + USBOTG3_CTRL0);
|
||||
|
||||
temp = readl(usb3otg_bc + USBOTG3_CTRL7);
|
||||
writel(temp | USB3OTG_CTRL7_REF_SSP_EN, usb3otg_bc + USBOTG3_CTRL7);
|
||||
|
||||
/* exit from IDDQ mode */
|
||||
temp = readl(usb3otg_bc + USBOTG3_CTRL2);
|
||||
writel(temp & ~(USB3OTG_CTRL2_TEST_POWERDOWN_SSP | USB3OTG_CTRL2_TEST_POWERDOWN_HSP), usb3otg_bc + USBOTG3_CTRL2);
|
||||
|
||||
mx_nanosleep(mx_deadline_after(MX_MSEC(10)));
|
||||
|
||||
writel(PERRSTEN4_USB3OTGPHY_POR, peri_crg + PERI_CRG_PERRSTDIS4);
|
||||
writel(PERRSTEN4_USB3OTG, peri_crg + PERI_CRG_PERRSTDIS4);
|
||||
|
||||
mx_nanosleep(mx_deadline_after(MX_MSEC(10)));
|
||||
|
||||
temp = readl(usb3otg_bc + USBOTG3_CTRL3);
|
||||
writel(temp | USB3OTG_CTRL3_VBUSVLDEXT | USB3OTG_CTRL3_VBUSVLDEXTSEL, usb3otg_bc + USBOTG3_CTRL7);
|
||||
|
||||
mx_nanosleep(mx_deadline_after(MX_MSEC(10)));
|
||||
|
||||
writel(0x1c466e3, usb3otg_bc + USBOTG3_CTRL4);
|
||||
|
||||
#if 0
|
||||
/* usb refclk iso enable */
|
||||
writel(USB_REFCLK_ISO_EN, peri_crg + PERI_CRG_ISODIS);
|
||||
|
||||
/* enable usb_tcxo_en */
|
||||
writel(USB_TCXO_EN | (USB_TCXO_EN << PERI_CTRL3_MSK_START),
|
||||
pctrl + PCTRL_PERI_CTRL3);
|
||||
|
||||
/* select usbphy clk from abb */
|
||||
uint32_t temp = readl(pctrl + PCTRL_PERI_CTRL24);
|
||||
temp &= ~SC_CLK_USB3PHY_3MUX1_SEL;
|
||||
writel(temp, pctrl + PCTRL_PERI_CTRL24);
|
||||
|
||||
/* open clk gate */
|
||||
writel(GT_CLK_USB3OTG_REF | GT_ACLK_USB3OTG,
|
||||
peri_crg + PERI_CRG_CLK_EN4);
|
||||
|
||||
#endif
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
static void hi3360_dwc3_release(void* ctx) {
|
||||
hi3360_dwc3_t* dwc = ctx;
|
||||
pdev_mmio_buffer_release(&dwc->usb3otg);
|
||||
pdev_mmio_buffer_release(&dwc->usb3otg_bc);
|
||||
pdev_mmio_buffer_release(&dwc->peri_crg);
|
||||
pdev_mmio_buffer_release(&dwc->pctrl);
|
||||
pdev_mmio_buffer_release(&dwc->sctrl);
|
||||
pdev_mmio_buffer_release(&dwc->pmctrl);
|
||||
free(dwc);
|
||||
}
|
||||
|
||||
static mx_status_t hi3360_dwc3_get_mmio(void* ctx, void** out_vaddr, size_t* out_length) {
|
||||
hi3360_dwc3_t* dwc = ctx;
|
||||
*out_vaddr = dwc->usb3otg.vaddr;
|
||||
*out_length = dwc->usb3otg.size;
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
static uint32_t hi3360_dwc3_get_interrupt_count(void* ctx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static mx_status_t hi3360_dwc3_get_interrupt(void* ctx, uint32_t index, mx_handle_t* out_handle) {
|
||||
hi3360_dwc3_t* dwc = ctx;
|
||||
if (index != 0) {
|
||||
return MX_ERR_INVALID_ARGS;
|
||||
}
|
||||
return pdev_map_interrupt(&dwc->pdev, 0, out_handle);
|
||||
}
|
||||
|
||||
static bool hi3360_dwc3_legacy_irq_mode(void* ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
usb_xhci_protocol_ops_t xhci_protocol = {
|
||||
.get_mmio = hi3360_dwc3_get_mmio,
|
||||
.get_interrupt_count = hi3360_dwc3_get_interrupt_count,
|
||||
.get_interrupt = hi3360_dwc3_get_interrupt,
|
||||
.legacy_irq_mode = hi3360_dwc3_legacy_irq_mode,
|
||||
};
|
||||
|
||||
static mx_protocol_device_t hi3360_dwc3_device_proto = {
|
||||
.version = DEVICE_OPS_VERSION,
|
||||
.release = hi3360_dwc3_release,
|
||||
};
|
||||
|
||||
static mx_status_t hi3360_dwc3_bind(void* ctx, mx_device_t* dev, void** cookie) {
|
||||
printf("hi3360_dwc3_bind\n");
|
||||
|
||||
hi3360_dwc3_t* dwc = calloc(1, sizeof(hi3360_dwc3_t));
|
||||
if (!dwc) {
|
||||
return MX_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
mx_status_t status = device_get_protocol(dev, MX_PROTOCOL_PLATFORM_DEV, &dwc->pdev);
|
||||
if (status != MX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
platform_device_protocol_t* pdev = &dwc->pdev;
|
||||
if ((status = pdev_map_mmio_buffer(pdev, MMIO_USB3OTG, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&dwc->usb3otg)) != MX_OK ||
|
||||
(status = pdev_map_mmio_buffer(pdev, MMIO_USB3OTG_BC, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&dwc->usb3otg_bc)) != MX_OK ||
|
||||
(status = pdev_map_mmio_buffer(pdev, MMIO_PERI_CRG, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&dwc->peri_crg)) != MX_OK ||
|
||||
(status = pdev_map_mmio_buffer(pdev, MMIO_PCTRL, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&dwc->pctrl)) != MX_OK ||
|
||||
(status = pdev_map_mmio_buffer(pdev, MMIO_SCTRL, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&dwc->sctrl)) != MX_OK ||
|
||||
(status = pdev_map_mmio_buffer(pdev, MMIO_PMCTRL, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&dwc->pmctrl)) != MX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printf("call hi3360_dwc3_init\n");
|
||||
if ((status = hi3360_dwc3_init(dwc)) != MX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
printf("did hi3360_dwc3_init\n");
|
||||
|
||||
|
||||
/*
|
||||
printf("usb3otg_bc:\n");
|
||||
hexdump8(dwc->usb3otg_bc.vaddr, 256);
|
||||
printf("peri_crg:\n");
|
||||
hexdump8(dwc->peri_crg.vaddr, 256);
|
||||
*/
|
||||
|
||||
// set host mode
|
||||
printf("set host mode\n");
|
||||
volatile void* usb3otg = dwc->usb3otg.vaddr;
|
||||
uint32_t temp = readl(usb3otg + GCTL);
|
||||
temp &= ~GCTL_PRTCAPDIR_MASK;
|
||||
temp |= GCTL_PRTCAPDIR_HOST;
|
||||
writel(temp, usb3otg + GCTL);
|
||||
printf("GCTL: %08X\n", temp);
|
||||
|
||||
|
||||
printf("usbotg:\n");
|
||||
hexdump(dwc->usb3otg.vaddr, 256);
|
||||
printf("global registers:\n");
|
||||
hexdump(dwc->usb3otg.vaddr + GSBUSCFG0, 256);
|
||||
printf("device registers:\n");
|
||||
hexdump(dwc->usb3otg.vaddr + DCFG, 256);
|
||||
|
||||
|
||||
device_add_args_t args = {
|
||||
.version = DEVICE_ADD_ARGS_VERSION,
|
||||
.name = "dwc3-xhci",
|
||||
.ctx = dwc,
|
||||
.ops = &hi3360_dwc3_device_proto,
|
||||
.proto_id = MX_PROTOCOL_USB_XHCI,
|
||||
.proto_ops = &xhci_protocol,
|
||||
};
|
||||
|
||||
status = device_add(dev, &args, &dwc->mxdev);
|
||||
if (status != MX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return MX_OK;
|
||||
|
||||
fail:
|
||||
printf("hi3360_dwc3_bind failed %d\n", status);
|
||||
hi3360_dwc3_release(dwc);
|
||||
return status;
|
||||
}
|
||||
|
||||
static mx_driver_ops_t hi3360_dwc3_driver_ops = {
|
||||
.version = DRIVER_OPS_VERSION,
|
||||
.bind = hi3360_dwc3_bind,
|
||||
};
|
||||
|
||||
// The formatter does not play nice with these macros.
|
||||
// clang-format off
|
||||
MAGENTA_DRIVER_BEGIN(hi3360_dwc3, hi3360_dwc3_driver_ops, "magenta", "0.1", 3)
|
||||
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, 0x12D1),
|
||||
BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, 0x0960),
|
||||
BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, 1),
|
||||
MAGENTA_DRIVER_END(hi3360_dwc3)
|
||||
// clang-format on
|
||||
@@ -0,0 +1,94 @@
|
||||
|
||||
#define USB_REFCLK_ISO_EN (1 << 25)
|
||||
|
||||
|
||||
#define PERI_CRG_PEREN2 0x020
|
||||
#define PERI_CRG_PERDIS2 0x024
|
||||
#define PERI_CRG_PERCLKEN2 0x028
|
||||
#define PERI_CRG_PERSTAT2 0x02C
|
||||
#define PERI_CRG_PEREN4 0x040
|
||||
#define PERI_CRG_PERDIS4 0x044
|
||||
#define PERI_CRG_PERCLKEN4 0x048
|
||||
#define PERI_CRG_PERSTAT4 0x04C
|
||||
#define PERI_CRG_PERRSTEN2 0x078
|
||||
#define PERI_CRG_PERRSTDIS2 0x07C
|
||||
#define PERI_CRG_PERRSTSTAT2 0x080
|
||||
#define PERI_CRG_PERRSTEN3 0x084
|
||||
#define PERI_CRG_PERRSTDIS3 0x088
|
||||
#define PERI_CRG_PERRSTSTAT3 0x08C
|
||||
#define PERI_CRG_PERRSTEN4 0x090
|
||||
#define PERI_CRG_PERRSTDIS4 0x094
|
||||
#define PERI_CRG_PERRSTSTAT4 0x098
|
||||
#define PERI_CRG_ISOEN 0x144
|
||||
#define PERI_CRG_ISODIS 0x148
|
||||
#define PERI_CRG_ISOSTAT 0x14C
|
||||
|
||||
#define PEREN4_GT_ACLK_USB3OTG (1 << 1)
|
||||
#define PEREN4_GT_CLK_USB3OTG_REF (1 << 0)
|
||||
|
||||
#define PERRSTEN4_USB3OTG_MUX (1 << 8)
|
||||
#define PERRSTEN4_USB3OTG_AHBIF (1 << 7)
|
||||
#define PERRSTEN4_USB3OTG_32K (1 << 6)
|
||||
#define PERRSTEN4_USB3OTG (1 << 5)
|
||||
#define PERRSTEN4_USB3OTGPHY_POR (1 << 3)
|
||||
|
||||
#define PERISOEN_USB_REFCLK_ISO_EN (1 << 25)
|
||||
|
||||
#define PERI_CRG_CLK_EN4 (0x40)
|
||||
#define PERI_CRG_CLK_DIS4 (0x44)
|
||||
#define PERI_CRG_RSTDIS4 (0x94)
|
||||
#define PERI_CRG_RSTEN4 (0x90)
|
||||
#define SC_CLK_USB3PHY_3MUX1_SEL (1 << 25)
|
||||
|
||||
#define PCTRL_CTRL3 0x10
|
||||
#define PCTRL_CTRL24 0x064
|
||||
|
||||
#define PCTRL_CTRL3_USB_TXCO_EN (1 << 1)
|
||||
#define PCTRL_CTRL24_USB3PHY_3MUX1_SEL (1 << 25)
|
||||
|
||||
#define USB_TCXO_EN (1 << 1)
|
||||
#define PERI_CTRL3_MSK_START (16)
|
||||
|
||||
#define GT_CLK_USB3OTG_REF (1 << 0)
|
||||
#define GT_ACLK_USB3OTG (1 << 1)
|
||||
#define GT_CLK_USB3PHY_REF (1 << 2)
|
||||
|
||||
// BC registers
|
||||
#define USBOTG3_CTRL0 0x00
|
||||
#define USBOTG3_CTRL1 0x04
|
||||
#define USBOTG3_CTRL2 0x08
|
||||
#define USBOTG3_CTRL3 0x0C
|
||||
#define USBOTG3_CTRL4 0x10
|
||||
#define USBOTG3_CTRL5 0x14
|
||||
#define USBOTG3_CTRL6 0x18
|
||||
#define USBOTG3_CTRL7 0x1C
|
||||
#define USBOTG3_STS0 0x20
|
||||
#define USBOTG3_STS1 0x24
|
||||
#define USBOTG3_STS2 0x28
|
||||
#define USBOTG3_STS3 0x2C
|
||||
#define BC_CTRL0 0x30
|
||||
#define BC_CTRL1 0x34
|
||||
#define BC_CTRL2 0x38
|
||||
#define BC_STS0 0x3C
|
||||
#define RAM_CTRL 0x40
|
||||
#define USBOTG3_STS4 0x44
|
||||
#define USB3PHY_CTRL 0x48
|
||||
#define USB3PHY_STS 0x4C
|
||||
#define USB3PHY_CR_STS 0x50
|
||||
#define USB3PHY_CR_CTRL 0x54
|
||||
#define USB3_RES 0x58
|
||||
|
||||
|
||||
#define USB3OTG_CTRL0_SC_USB3PHY_ABB_GT_EN (1 << 15)
|
||||
#define USB3OTG_CTRL2_TEST_POWERDOWN_SSP (1 << 1)
|
||||
#define USB3OTG_CTRL2_TEST_POWERDOWN_HSP (1 << 0)
|
||||
#define USB3OTG_CTRL3_VBUSVLDEXT (1 << 6)
|
||||
#define USB3OTG_CTRL3_VBUSVLDEXTSEL (1 << 5)
|
||||
#define USB3OTG_CTRL7_REF_SSP_EN (1 << 16)
|
||||
#define USB3OTG_PHY_CR_DATA_OUT(x) (((x) & 0xFFFF) << 1)
|
||||
#define USB3OTG_PHY_CR_ACK (1 << 0)
|
||||
#define USB3OTG_PHY_CR_DATA_IN(x) (((x) & 0xFFFF) << 4)
|
||||
#define USB3OTG_PHY_CR_WRITE (1 << 3)
|
||||
#define USB3OTG_PHY_CR_READ (1 << 2)
|
||||
#define USB3OTG_PHY_CR_CAP_DATA (1 << 1)
|
||||
#define USB3OTG_PHY_CR_CAP_ADDR (1 << 0)
|
||||
@@ -0,0 +1,18 @@
|
||||
# Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
MODULE_TYPE := driver
|
||||
|
||||
MODULE_SRCS += \
|
||||
$(LOCAL_DIR)/hi3660-dwc3.c
|
||||
|
||||
MODULE_STATIC_LIBS := system/ulib/ddk system/ulib/sync system/ulib/pretty
|
||||
|
||||
MODULE_LIBS := system/ulib/driver system/ulib/magenta system/ulib/c
|
||||
|
||||
include make/module.mk
|
||||
@@ -0,0 +1,18 @@
|
||||
# Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
LOCAL_DIR := $(GET_LOCAL_DIR)
|
||||
|
||||
MODULE := $(LOCAL_DIR)
|
||||
|
||||
MODULE_TYPE := driver
|
||||
|
||||
MODULE_SRCS := \
|
||||
$(LOCAL_DIR)/xhci-pci.c \
|
||||
|
||||
MODULE_STATIC_LIBS := system/ulib/ddk
|
||||
|
||||
MODULE_LIBS := system/ulib/driver system/ulib/magenta system/ulib/c
|
||||
|
||||
include make/module.mk
|
||||
@@ -0,0 +1,156 @@
|
||||
// Copyright 2016 The Fuchsia Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <ddk/binding.h>
|
||||
#include <ddk/device.h>
|
||||
#include <ddk/driver.h>
|
||||
#include <ddk/protocol/pci.h>
|
||||
#include <ddk/protocol/usb-xhci.h>
|
||||
|
||||
#include <hw/reg.h>
|
||||
#include <magenta/syscalls.h>
|
||||
#include <magenta/types.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
mx_device_t* mxdev;
|
||||
pci_protocol_t pci;
|
||||
mx_handle_t cfg_handle;
|
||||
mx_handle_t mmio_handle;
|
||||
void* mmio;
|
||||
size_t mmio_length;
|
||||
bool legacy_irq_mode;
|
||||
} xhci_pci_t;
|
||||
|
||||
static mx_status_t xhci_pci_get_mmio(void* ctx, void** out_vaddr, size_t* out_length) {
|
||||
xhci_pci_t* xhci = ctx;
|
||||
*out_vaddr = xhci->mmio;
|
||||
*out_length = xhci->mmio_length;
|
||||
return MX_OK;
|
||||
}
|
||||
|
||||
static uint32_t xhci_pci_get_interrupt_count(void* ctx) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static mx_status_t xhci_pci_get_interrupt(void* ctx, uint32_t index, mx_handle_t* out_handle) {
|
||||
xhci_pci_t* xhci = ctx;
|
||||
return pci_map_interrupt(&xhci->pci, index, out_handle);
|
||||
}
|
||||
|
||||
static bool xhci_pci_legacy_irq_mode(void* ctx) {
|
||||
xhci_pci_t* xhci = ctx;
|
||||
return xhci->legacy_irq_mode;
|
||||
}
|
||||
|
||||
usb_xhci_protocol_ops_t xhci_protocol = {
|
||||
.get_mmio = xhci_pci_get_mmio,
|
||||
.get_interrupt_count = xhci_pci_get_interrupt_count,
|
||||
.get_interrupt = xhci_pci_get_interrupt,
|
||||
.legacy_irq_mode = xhci_pci_legacy_irq_mode,
|
||||
};
|
||||
|
||||
static void xhci_pci_unbind(void* ctx) {
|
||||
xhci_pci_t* xhci = ctx;
|
||||
device_remove(xhci->mxdev);
|
||||
}
|
||||
|
||||
static void xhci_pci_release(void* ctx) {
|
||||
xhci_pci_t* xhci = ctx;
|
||||
|
||||
if (xhci->mmio) {
|
||||
mx_vmar_unmap(mx_vmar_root_self(), (uintptr_t)xhci->mmio, xhci->mmio_length);
|
||||
}
|
||||
mx_handle_close(xhci->cfg_handle);
|
||||
mx_handle_close(xhci->mmio_handle);
|
||||
free(xhci);
|
||||
}
|
||||
|
||||
static mx_protocol_device_t xhci_pci_device_proto = {
|
||||
.version = DEVICE_OPS_VERSION,
|
||||
.unbind = xhci_pci_unbind,
|
||||
.release = xhci_pci_release,
|
||||
};
|
||||
|
||||
static mx_status_t xhci_pci_bind(void* ctx, mx_device_t* dev, void** cookie) {
|
||||
mx_status_t status;
|
||||
|
||||
xhci_pci_t* xhci = calloc(1, sizeof(xhci_pci_t));
|
||||
if (!xhci) {
|
||||
return MX_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
status = device_get_protocol(dev, MX_PROTOCOL_PCI, &xhci->pci);
|
||||
if (status != MX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/*
|
||||
* eXtensible Host Controller Interface revision 1.1, section 5, xhci
|
||||
* should only use BARs 0 and 1. 0 for 32 bit addressing, and 0+1 for 64 bit addressing.
|
||||
*/
|
||||
status = pci_map_resource(&xhci->pci, PCI_RESOURCE_BAR_0, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&xhci->mmio, &xhci->mmio_length, &xhci->mmio_handle);
|
||||
if (status != MX_OK) {
|
||||
printf("xhci_pci_bind could not find bar\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// enable bus master
|
||||
status = pci_enable_bus_master(&xhci->pci, true);
|
||||
if (status != MX_OK) {
|
||||
printf("xhci_pci_bind enable_bus_master failed %d\n", status);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// select our IRQ mode
|
||||
status = pci_set_irq_mode(&xhci->pci, MX_PCIE_IRQ_MODE_MSI, 1);
|
||||
if (status != MX_OK) {
|
||||
mx_status_t status_legacy = pci_set_irq_mode(&xhci->pci, MX_PCIE_IRQ_MODE_LEGACY, 1);
|
||||
|
||||
if (status_legacy != MX_OK) {
|
||||
printf("xhci_pci_bind Failed to set IRQ mode to either MSI "
|
||||
"(err = %d) or Legacy (err = %d)\n",
|
||||
status, status_legacy);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
xhci->legacy_irq_mode = true;
|
||||
}
|
||||
|
||||
device_add_args_t args = {
|
||||
.version = DEVICE_ADD_ARGS_VERSION,
|
||||
.name = "xhci-pci",
|
||||
.ctx = xhci,
|
||||
.ops = &xhci_pci_device_proto,
|
||||
.proto_id = MX_PROTOCOL_USB_XHCI,
|
||||
.proto_ops = &xhci_protocol,
|
||||
};
|
||||
|
||||
status = device_add(dev, &args, &xhci->mxdev);
|
||||
if (status != MX_OK) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return MX_OK;
|
||||
|
||||
fail:
|
||||
xhci_pci_release(xhci);
|
||||
return status;
|
||||
}
|
||||
|
||||
static mx_driver_ops_t xhci_pci_driver_ops = {
|
||||
.version = DRIVER_OPS_VERSION,
|
||||
.bind = xhci_pci_bind,
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
MAGENTA_DRIVER_BEGIN(xhci_pci, xhci_pci_driver_ops, "magenta", "0.1", 4)
|
||||
BI_ABORT_IF(NE, BIND_PROTOCOL, MX_PROTOCOL_PCI),
|
||||
BI_ABORT_IF(NE, BIND_PCI_CLASS, 0x0C),
|
||||
BI_ABORT_IF(NE, BIND_PCI_SUBCLASS, 0x03),
|
||||
BI_MATCH_IF(EQ, BIND_PCI_INTERFACE, 0x30),
|
||||
MAGENTA_DRIVER_END(xhci_pci)
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <ddk/binding.h>
|
||||
#include <ddk/driver.h>
|
||||
#include <ddk/protocol/usb-hci.h>
|
||||
#include <ddk/protocol/usb-xhci.h>
|
||||
#include <ddk/protocol/usb.h>
|
||||
|
||||
#include <hw/reg.h>
|
||||
@@ -14,13 +15,14 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <threads.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "xhci-device-manager.h"
|
||||
#include "xhci-root-hub.h"
|
||||
#include "xhci-util.h"
|
||||
#include "xhci.h"
|
||||
|
||||
//#define TRACE 1
|
||||
#define TRACE 1
|
||||
#include "xhci-debug.h"
|
||||
|
||||
#define MAX_SLOTS 255
|
||||
@@ -150,9 +152,8 @@ static void xhci_unbind(void* ctx) {
|
||||
}
|
||||
|
||||
static void xhci_release(void* ctx) {
|
||||
xhci_t* xhci = ctx;
|
||||
|
||||
// FIXME(voydanoff) - there is a lot more work to do here
|
||||
xhci_t* xhci = ctx;
|
||||
mx_handle_close(xhci->irq_handle);
|
||||
free(xhci);
|
||||
}
|
||||
|
||||
@@ -194,6 +195,7 @@ static int xhci_irq_thread(void* arg) {
|
||||
mx_thread_set_priority(24 /* HIGH_PRIORITY in LK */);
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
mx_status_t wait_res;
|
||||
|
||||
wait_res = mx_interrupt_wait(xhci->irq_handle);
|
||||
@@ -203,86 +205,70 @@ static int xhci_irq_thread(void* arg) {
|
||||
break;
|
||||
}
|
||||
|
||||
mx_interrupt_complete(xhci->irq_handle);
|
||||
xhci_handle_interrupt(xhci, xhci->legacy_irq_mode);
|
||||
mx_interrupt_complete(xhci->irq_handle)
|
||||
*/
|
||||
xhci_handle_interrupt(xhci);
|
||||
sleep(1);
|
||||
}
|
||||
xprintf("xhci_irq_thread done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mx_status_t usb_xhci_bind(void* ctx, mx_device_t* dev, void** cookie) {
|
||||
printf("usb_xhci_bind\n");
|
||||
mx_handle_t irq_handle = MX_HANDLE_INVALID;
|
||||
mx_handle_t mmio_handle = MX_HANDLE_INVALID;
|
||||
mx_handle_t cfg_handle = MX_HANDLE_INVALID;
|
||||
xhci_t* xhci = NULL;
|
||||
mx_status_t status;
|
||||
|
||||
pci_protocol_t pci;
|
||||
if (device_get_protocol(dev, MX_PROTOCOL_PCI, &pci)) {
|
||||
usb_xhci_protocol_t xhci_proto;
|
||||
if (device_get_protocol(dev, MX_PROTOCOL_USB_XHCI, &xhci_proto)) {
|
||||
printf("usb_xhci_bind MX_ERR_NOT_SUPPORTED\n");
|
||||
status = MX_ERR_NOT_SUPPORTED;
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
xhci = calloc(1, sizeof(xhci_t));
|
||||
if (!xhci) {
|
||||
printf("usb_xhci_bind MX_ERR_NO_MEMORY\n");
|
||||
status = MX_ERR_NO_MEMORY;
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
printf("usb_xhci_bind aa\n");
|
||||
void* mmio;
|
||||
uint64_t mmio_len;
|
||||
/*
|
||||
* eXtensible Host Controller Interface revision 1.1, section 5, xhci
|
||||
* should only use BARs 0 and 1. 0 for 32 bit addressing, and 0+1 for 64 bit addressing.
|
||||
*/
|
||||
status = pci_map_resource(&pci, PCI_RESOURCE_BAR_0, MX_CACHE_POLICY_UNCACHED_DEVICE,
|
||||
&mmio, &mmio_len, &mmio_handle);
|
||||
status = usb_xhci_get_mmio(&xhci_proto, &mmio, &mmio_len);
|
||||
if (status != MX_OK) {
|
||||
printf("usb_xhci_bind could not find bar\n");
|
||||
status = MX_ERR_INTERNAL;
|
||||
printf("usb_xhci_bind: usb_xhci_get_mmio failed\n");
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
// enable bus master
|
||||
status = pci_enable_bus_master(&pci, true);
|
||||
if (status < 0) {
|
||||
printf("usb_xhci_bind enable_bus_master failed %d\n", status);
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
// select our IRQ mode
|
||||
status = pci_set_irq_mode(&pci, MX_PCIE_IRQ_MODE_MSI, 1);
|
||||
if (status < 0) {
|
||||
mx_status_t status_legacy = pci_set_irq_mode(&pci, MX_PCIE_IRQ_MODE_LEGACY, 1);
|
||||
|
||||
if (status_legacy < 0) {
|
||||
printf("usb_xhci_bind Failed to set IRQ mode to either MSI "
|
||||
"(err = %d) or Legacy (err = %d)\n",
|
||||
status, status_legacy);
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
xhci->legacy_irq_mode = true;
|
||||
}
|
||||
printf("usb_xhci_bind 2\n");
|
||||
|
||||
// register for interrupts
|
||||
status = pci_map_interrupt(&pci, 0, &irq_handle);
|
||||
status = usb_xhci_get_interrupt(&xhci_proto, 0, &irq_handle);
|
||||
if (status != MX_OK) {
|
||||
printf("usb_xhci_bind map_interrupt failed %d\n", status);
|
||||
printf("usb_xhci_bind: usb_xhci_get_interrupt failed %d\n", status);
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
printf("usb_xhci_bind 3\n");
|
||||
|
||||
xhci->irq_handle = irq_handle;
|
||||
xhci->mmio_handle = mmio_handle;
|
||||
xhci->cfg_handle = cfg_handle;
|
||||
xhci->legacy_irq_mode = usb_xhci_legacy_irq_mode(&xhci_proto);
|
||||
|
||||
// stash this here for the startup thread to call device_add() with
|
||||
xhci->parent = dev;
|
||||
|
||||
printf("call xhci_init\n");
|
||||
status = xhci_init(xhci, mmio);
|
||||
if (status != MX_OK) {
|
||||
goto error_return;
|
||||
}
|
||||
printf("usb_xhci_bind 4\n");
|
||||
|
||||
thrd_t thread;
|
||||
thrd_create_with_name(&thread, xhci_irq_thread, xhci, "xhci_irq_thread");
|
||||
@@ -291,18 +277,13 @@ static mx_status_t usb_xhci_bind(void* ctx, mx_device_t* dev, void** cookie) {
|
||||
return MX_OK;
|
||||
|
||||
error_return:
|
||||
printf("bind failed\n");
|
||||
if (xhci) {
|
||||
free(xhci);
|
||||
}
|
||||
if (irq_handle != MX_HANDLE_INVALID) {
|
||||
mx_handle_close(irq_handle);
|
||||
}
|
||||
if (mmio_handle != MX_HANDLE_INVALID) {
|
||||
mx_handle_close(mmio_handle);
|
||||
}
|
||||
if (cfg_handle != MX_HANDLE_INVALID) {
|
||||
mx_handle_close(cfg_handle);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -312,9 +293,6 @@ static mx_driver_ops_t xhci_driver_ops = {
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
MAGENTA_DRIVER_BEGIN(usb_xhci, xhci_driver_ops, "magenta", "0.1", 4)
|
||||
BI_ABORT_IF(NE, BIND_PROTOCOL, MX_PROTOCOL_PCI),
|
||||
BI_ABORT_IF(NE, BIND_PCI_CLASS, 0x0C),
|
||||
BI_ABORT_IF(NE, BIND_PCI_SUBCLASS, 0x03),
|
||||
BI_MATCH_IF(EQ, BIND_PCI_INTERFACE, 0x30),
|
||||
MAGENTA_DRIVER_BEGIN(usb_xhci, xhci_driver_ops, "magenta", "0.1", 1)
|
||||
BI_MATCH_IF(EQ, BIND_PROTOCOL, MX_PROTOCOL_USB_XHCI),
|
||||
MAGENTA_DRIVER_END(usb_xhci)
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "xhci-root-hub.h"
|
||||
#include "xhci-transfer.h"
|
||||
|
||||
//#define TRACE 1
|
||||
#define TRACE 1
|
||||
#include "xhci-debug.h"
|
||||
|
||||
#define PAGE_ROUNDUP(x) ((x + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
|
||||
@@ -193,6 +193,7 @@ mx_status_t xhci_init(xhci_t* xhci, void* mmio) {
|
||||
mx_status_t result = MX_OK;
|
||||
mx_paddr_t* phys_addrs = NULL;
|
||||
|
||||
printf("xhci_init 1\n");
|
||||
list_initialize(&xhci->command_queue);
|
||||
mtx_init(&xhci->command_ring_lock, mtx_plain);
|
||||
mtx_init(&xhci->command_queue_mutex, mtx_plain);
|
||||
@@ -200,10 +201,16 @@ mx_status_t xhci_init(xhci_t* xhci, void* mmio) {
|
||||
mtx_init(&xhci->input_context_lock, mtx_plain);
|
||||
completion_reset(&xhci->command_queue_completion);
|
||||
|
||||
printf("xhci_init 2\n");
|
||||
xhci->cap_regs = (xhci_cap_regs_t*)mmio;
|
||||
printf("xhci->cap_regs %p\n", xhci->cap_regs);
|
||||
printf("xhci->cap_regs->length %u\n", xhci->cap_regs->length);
|
||||
xhci->op_regs = (xhci_op_regs_t*)((uint8_t*)xhci->cap_regs + xhci->cap_regs->length);
|
||||
printf("xhci->op_regs %p\n", xhci->op_regs);
|
||||
xhci->doorbells = (uint32_t*)((uint8_t*)xhci->cap_regs + xhci->cap_regs->dboff);
|
||||
printf("xhci->doorbells %p\n", xhci->doorbells);
|
||||
xhci->runtime_regs = (xhci_runtime_regs_t*)((uint8_t*)xhci->cap_regs + xhci->cap_regs->rtsoff);
|
||||
printf("xhci->runtime_regs %p\n", xhci->runtime_regs);
|
||||
volatile uint32_t* hcsparams1 = &xhci->cap_regs->hcsparams1;
|
||||
volatile uint32_t* hcsparams2 = &xhci->cap_regs->hcsparams2;
|
||||
volatile uint32_t* hccparams1 = &xhci->cap_regs->hccparams1;
|
||||
@@ -211,12 +218,17 @@ mx_status_t xhci_init(xhci_t* xhci, void* mmio) {
|
||||
|
||||
xhci->max_slots = XHCI_GET_BITS32(hcsparams1, HCSPARAMS1_MAX_SLOTS_START,
|
||||
HCSPARAMS1_MAX_SLOTS_BITS);
|
||||
printf("xhci->max_slots %zu\n", xhci->max_slots);
|
||||
xhci->max_interruptors = XHCI_GET_BITS32(hcsparams1, HCSPARAMS1_MAX_INTRS_START,
|
||||
HCSPARAMS1_MAX_INTRS_BITS);
|
||||
printf("xhci->max_interruptors %zu\n", xhci->max_interruptors);
|
||||
xhci->rh_num_ports = XHCI_GET_BITS32(hcsparams1, HCSPARAMS1_MAX_PORTS_START,
|
||||
HCSPARAMS1_MAX_PORTS_BITS);
|
||||
printf("xhci->rh_num_ports %u\n", xhci->rh_num_ports);
|
||||
xhci->context_size = (XHCI_READ32(hccparams1) & HCCPARAMS1_CSZ ? 64 : 32);
|
||||
printf("xhci->context_size %zu\n", xhci->context_size);
|
||||
xhci->large_esit = !!(XHCI_READ32(hccparams2) & HCCPARAMS2_LEC);
|
||||
printf("xhci->large_esit %u\n", xhci->large_esit);
|
||||
|
||||
uint32_t scratch_pad_bufs = XHCI_GET_BITS32(hcsparams2, HCSPARAMS2_MAX_SBBUF_HI_START,
|
||||
HCSPARAMS2_MAX_SBBUF_HI_BITS);
|
||||
@@ -224,6 +236,7 @@ mx_status_t xhci_init(xhci_t* xhci, void* mmio) {
|
||||
scratch_pad_bufs |= XHCI_GET_BITS32(hcsparams2, HCSPARAMS2_MAX_SBBUF_LO_START,
|
||||
HCSPARAMS2_MAX_SBBUF_LO_BITS);
|
||||
xhci->page_size = XHCI_READ32(&xhci->op_regs->pagesize) << 12;
|
||||
printf("xhci->page_size %zu\n", xhci->page_size);
|
||||
|
||||
// allocate array to hold our slots
|
||||
// add 1 to allow 1-based indexing of slots
|
||||
@@ -570,17 +583,19 @@ static void xhci_handle_events(xhci_t* xhci, int interruptor) {
|
||||
}
|
||||
}
|
||||
|
||||
void xhci_handle_interrupt(xhci_t* xhci, bool legacy) {
|
||||
void xhci_handle_interrupt(xhci_t* xhci) {
|
||||
|
||||
volatile uint32_t* usbsts = &xhci->op_regs->usbsts;
|
||||
const int interruptor = 0;
|
||||
|
||||
uint32_t status = XHCI_READ32(usbsts);
|
||||
printf("xhci_handle_interrupt status %p: %08X\n", usbsts, status);
|
||||
uint32_t clear = status & USBSTS_CLEAR_BITS;
|
||||
XHCI_WRITE32(usbsts, clear);
|
||||
|
||||
// If we are in legacy IRQ mode, clear the IP (Interrupt Pending) bit
|
||||
// from the IMAN register of our interrupter.
|
||||
if (legacy) {
|
||||
if (xhci->legacy_irq_mode) {
|
||||
xhci_intr_regs_t* intr_regs = &xhci->runtime_regs->intr_regs[interruptor];
|
||||
XHCI_SET32(&intr_regs->iman, IMAN_IP, IMAN_IP);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include <threads.h>
|
||||
|
||||
#include <ddk/device.h>
|
||||
#include <ddk/protocol/pci.h>
|
||||
#include <ddk/protocol/usb-bus.h>
|
||||
|
||||
#include "xhci-hw.h"
|
||||
@@ -84,8 +83,6 @@ struct xhci {
|
||||
|
||||
bool legacy_irq_mode;
|
||||
mx_handle_t irq_handle;
|
||||
mx_handle_t mmio_handle;
|
||||
mx_handle_t cfg_handle;
|
||||
thrd_t irq_thread;
|
||||
|
||||
// used by the start thread
|
||||
@@ -174,7 +171,7 @@ mx_status_t xhci_endpoint_init(xhci_endpoint_t* ep, int ring_count);
|
||||
void xhci_endpoint_free(xhci_endpoint_t* ep);
|
||||
int xhci_get_ep_state(xhci_endpoint_t* ep);
|
||||
void xhci_start(xhci_t* xhci);
|
||||
void xhci_handle_interrupt(xhci_t* xhci, bool legacy);
|
||||
void xhci_handle_interrupt(xhci_t* xhci);
|
||||
void xhci_post_command(xhci_t* xhci, uint32_t command, uint64_t ptr, uint32_t control_bits,
|
||||
xhci_command_context_t* context);
|
||||
void xhci_wait_bits(volatile uint32_t* ptr, uint32_t bits, uint32_t expected);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <magenta/compiler.h>
|
||||
#include <magenta/process.h>
|
||||
#include <magenta/types.h>
|
||||
|
||||
__BEGIN_CDECLS;
|
||||
@@ -40,8 +41,8 @@ static inline mx_status_t pbus_interface_add_gpios(pbus_interface_t* intf, uint3
|
||||
typedef struct {
|
||||
mx_status_t (*set_interface)(void* ctx, pbus_interface_t* interface);
|
||||
mx_status_t (*get_protocol)(void* ctx, uint32_t proto_id, void* out);
|
||||
mx_status_t (*map_mmio)(void* ctx, uint32_t index, uint32_t cache_policy, void** vaddr,
|
||||
size_t* size, mx_handle_t* out_handle);
|
||||
mx_status_t (*map_mmio)(void* ctx, uint32_t index, uint32_t cache_policy, void** out_vaddr,
|
||||
size_t* out_size, mx_handle_t* out_handle);
|
||||
|
||||
mx_status_t (*map_interrupt)(void* ctx, uint32_t index, mx_handle_t* out_handle);
|
||||
} platform_device_protocol_ops_t;
|
||||
@@ -65,9 +66,9 @@ static inline mx_status_t pdev_get_protocol(platform_device_protocol_t* pdev, ui
|
||||
// Maps an MMIO region based on information in the MDI
|
||||
// index is based on ordering of the device's mmio nodes in the MDI
|
||||
static inline mx_status_t pdev_map_mmio(platform_device_protocol_t* pdev, uint32_t index,
|
||||
uint32_t cache_policy, void** vaddr, size_t* size,
|
||||
uint32_t cache_policy, void** out_vaddr, size_t* out_size,
|
||||
mx_handle_t* out_handle) {
|
||||
return pdev->ops->map_mmio(pdev->ctx, index, cache_policy, vaddr, size, out_handle);
|
||||
return pdev->ops->map_mmio(pdev->ctx, index, cache_policy, out_vaddr, out_size, out_handle);
|
||||
}
|
||||
|
||||
// Returns an interrupt handle for an IRQ based on information in the MDI
|
||||
@@ -77,4 +78,25 @@ static inline mx_status_t pdev_map_interrupt(platform_device_protocol_t* pdev, u
|
||||
return pdev->ops->map_interrupt(pdev->ctx, index, out_handle);
|
||||
}
|
||||
|
||||
// MMIO mapping helpers
|
||||
|
||||
typedef struct {
|
||||
void* vaddr;
|
||||
size_t size;
|
||||
mx_handle_t handle;
|
||||
} pdev_mmio_buffer_t;
|
||||
|
||||
static inline mx_status_t pdev_map_mmio_buffer(platform_device_protocol_t* pdev, uint32_t index,
|
||||
uint32_t cache_policy, pdev_mmio_buffer_t* buffer) {
|
||||
return pdev->ops->map_mmio(pdev->ctx, index, cache_policy, &buffer->vaddr, &buffer->size,
|
||||
&buffer->handle);
|
||||
}
|
||||
|
||||
static inline void pdev_mmio_buffer_release(pdev_mmio_buffer_t* buffer) {
|
||||
if (buffer->vaddr) {
|
||||
mx_vmar_unmap(mx_vmar_root_self(), (uintptr_t)buffer->vaddr, buffer->size);
|
||||
}
|
||||
mx_handle_close(buffer->handle);
|
||||
}
|
||||
|
||||
__END_CDECLS;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2017 The Fuchsia Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <magenta/compiler.h>
|
||||
#include <magenta/process.h>
|
||||
#include <magenta/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
__BEGIN_CDECLS;
|
||||
|
||||
typedef struct {
|
||||
mx_status_t (*get_mmio)(void* ctx, void** out_vaddr, size_t* out_length);
|
||||
uint32_t (*get_interrupt_count)(void* ctx);
|
||||
mx_status_t (*get_interrupt)(void* ctx, uint32_t index, mx_handle_t* out_handle);
|
||||
bool (*legacy_irq_mode)(void* ctx);
|
||||
} usb_xhci_protocol_ops_t;
|
||||
|
||||
typedef struct {
|
||||
usb_xhci_protocol_ops_t* ops;
|
||||
void* ctx;
|
||||
} usb_xhci_protocol_t;
|
||||
|
||||
// returns pointer and size to XHCI MMIO region.
|
||||
// parent device is responsible for unmapping.
|
||||
static inline mx_status_t usb_xhci_get_mmio(usb_xhci_protocol_t* xhci, void** out_vaddr,
|
||||
size_t* out_length) {
|
||||
return xhci->ops->get_mmio(xhci->ctx, out_vaddr, out_length);
|
||||
}
|
||||
|
||||
// returns number of interrupts supported
|
||||
static inline uint32_t usb_xhci_get_interrupt_count(usb_xhci_protocol_t* xhci) {
|
||||
return xhci->ops->get_interrupt_count(xhci->ctx);
|
||||
}
|
||||
|
||||
// returns an interrupt handle for the specified interrupt index
|
||||
// caller takes ownership of the handle
|
||||
static inline mx_status_t usb_xhci_get_interrupt(usb_xhci_protocol_t* xhci, uint32_t index,
|
||||
mx_handle_t* out_handle) {
|
||||
return xhci->ops->get_interrupt(xhci->ctx, index, out_handle);
|
||||
}
|
||||
|
||||
// returns true if we are in PCI legacy mode
|
||||
static inline bool usb_xhci_legacy_irq_mode(usb_xhci_protocol_t* xhci) {
|
||||
return xhci->ops->legacy_irq_mode(xhci->ctx);
|
||||
}
|
||||
|
||||
__END_CDECLS;
|
||||
@@ -28,8 +28,9 @@ DDK_PROTOCOL_DEF(MISC_PARENT, 'pMSP', "misc-parent", PF_NOPUB)
|
||||
DDK_PROTOCOL_DEF(PCI, 'pPCI', "pci", 0)
|
||||
DDK_PROTOCOL_DEF(TPM, 'pTPM', "tpm", 0)
|
||||
DDK_PROTOCOL_DEF(USB, 'pUSB', "usb", 0)
|
||||
DDK_PROTOCOL_DEF(USB_HCI, 'pUHI', "usb-hci", 0)
|
||||
DDK_PROTOCOL_DEF(USB_BUS, 'pUBS', "usb-bus", 0)
|
||||
DDK_PROTOCOL_DEF(USB_HCI, 'pUHI', "usb-hci", 0)
|
||||
DDK_PROTOCOL_DEF(USB_XHCI, 'pUXI', "usb-xhci", 0)
|
||||
DDK_PROTOCOL_DEF(BLUETOOTH_HCI, 'pBHC', "bt-hci", 0)
|
||||
DDK_PROTOCOL_DEF(AUDIO, 'pAUD', "audio", 0)
|
||||
DDK_PROTOCOL_DEF(MIDI, 'pMID', "midi", 0)
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário