Comparar commits

...

7 Commits

Autor SHA1 Mensagem Data
Mike Voydanoff f48cef3768 more wip
Change-Id: I9be5462819ffdaa23af0b874a15d0959d640a4e3
2017-07-25 11:33:54 -07:00
Mike Voydanoff cd8fd74356 start on dwc3 xhci
Change-Id: I30a1170e313d869f316154d76bed86524bbc8ff9
2017-07-25 08:19:48 -07:00
Mike Voydanoff 819f8ab8c4 [dev][usb-xhci] Move PCI specific parts to a separate driver
A new driver called xhci-pci handles the PCI specific functionality.
This driver exposes a new protocol MX_PROTOCOL_USB_XHCI that the
usb-xhci driver now binds to.
This will allow us to use the usb-xhci driver on non-PCI platforms
such as ARM SOCs with dwc3 support.

Change-Id: Icf84d2bb3334bafb340cdadc9f7833e7bb768c29
2017-07-25 08:17:53 -07:00
Mike Voydanoff 937a808501 Seem to have brought up the USB MMIOs!
Change-Id: I850fa28eb9ab805d7d77bb9bfbca7d8e0a86ed42
2017-07-25 08:16:34 -07:00
Mike Voydanoff c2a4304217 start on registers
Change-Id: Ic118c31a73162779b0b6234112e3ca76ef7eab91
2017-07-25 07:04:32 -07:00
Mike Voydanoff 72efa255f4 start on dwc3 driver. just mapping mmios so far
Change-Id: Ia0c5e21fc7cad4d4dbe0f2d865df0a6832b6b111
2017-07-25 07:04:31 -07:00
Mike Voydanoff acce76482c [ddk][platform-device] Add helper for mapping MMIO regions
Change-Id: I75442540c4484cc463527f0658f352112692194e
2017-07-25 07:04:31 -07:00
13 arquivos alterados com 1023 adições e 63 exclusões
+42
Ver Arquivo
@@ -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 */,
]
}
}
+304
Ver Arquivo
@@ -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
+265
Ver Arquivo
@@ -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
+94
Ver Arquivo
@@ -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)
+18
Ver Arquivo
@@ -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
+18
Ver Arquivo
@@ -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
+156
Ver Arquivo
@@ -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)
+29 -51
Ver Arquivo
@@ -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 -3
Ver Arquivo
@@ -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);
}
+1 -4
Ver Arquivo
@@ -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;
+2 -1
Ver Arquivo
@@ -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)