From patchwork Wed Feb 15 14:54:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 94018 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp2063995qgi; Wed, 15 Feb 2017 06:55:33 -0800 (PST) X-Received: by 10.55.148.133 with SMTP id w127mr36917127qkd.217.1487170533094; Wed, 15 Feb 2017 06:55:33 -0800 (PST) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id d39si2982558qtf.224.2017.02.15.06.55.32; Wed, 15 Feb 2017 06:55:33 -0800 (PST) Received-SPF: pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=linaro-uefi-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 7CF1062D3B; Wed, 15 Feb 2017 14:55:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 2F64A62D90; Wed, 15 Feb 2017 14:55:16 +0000 (UTC) X-Original-To: linaro-uefi@lists.linaro.org Delivered-To: linaro-uefi@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 6DB1262CFE; Wed, 15 Feb 2017 14:55:12 +0000 (UTC) Received: from mail-pf0-f172.google.com (mail-pf0-f172.google.com [209.85.192.172]) by lists.linaro.org (Postfix) with ESMTPS id 0545E60C29 for ; Wed, 15 Feb 2017 14:55:10 +0000 (UTC) Received: by mail-pf0-f172.google.com with SMTP id 189so32173306pfu.3 for ; Wed, 15 Feb 2017 06:55:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=cI+Yl39btELp2qS4hRBQ7Zn2WSc/5rqW5bpIsMSC6y0=; b=qdthzQvGtnkg0jxu2wJBTMnxg6fA1nebPXB7ZC0v/kNoZQFXlegK1BRQewvvhKhf5s ofWd59WctImP2ywOws31/aJ6dbLbsMnJaQCEFCnnvB+CxJ63nnCAILf6Xp41LAVPBMn9 0pRtmBRmJSIXlwRYb6Tpn+Sm3N0vAwT6QgMBmDDoNgLR+CqqDINkWuhMB1JQQPvn8OSh rNXM58rBU49EEvUC0XqtMe7IifRIG8WoIPvW8UbRFGUNQOrHOMF3CxuIQahMdpUcev6t 9zSTnGLbiQIntgtf2q/g0ZtC3zXSPwk1mEqFx/v1I/+4BDtGC8resAOI2td0lnXFk3he vj3Q== X-Gm-Message-State: AMke39kGPxqf8w5yF3rBtYu5/0+NIY9vpvJTDJ49GsAWhKr3IjtBeCfn2uSNxZxokrFs7I4nsNw= X-Received: by 10.84.216.93 with SMTP id f29mr24033764plj.10.1487170509316; Wed, 15 Feb 2017 06:55:09 -0800 (PST) Received: from localhost.localdomain ([45.56.159.211]) by smtp.gmail.com with ESMTPSA id s24sm8212782pgo.25.2017.02.15.06.55.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Feb 2017 06:55:08 -0800 (PST) From: Haojian Zhuang To: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org Date: Wed, 15 Feb 2017 22:54:55 +0800 Message-Id: <1487170499-22374-2-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> References: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> Subject: [Linaro-uefi] [PATCH v4 1/5] Platforms/Hisilicon/HiKey: append more register definitions X-BeenThere: linaro-uefi@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-uefi-bounces@lists.linaro.org Sender: "Linaro-uefi" Add more register definitions in Hi6220 SoC. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang Reviewed-by: Leif Lindholm --- Chips/Hisilicon/Hi6220/Include/Hi6220.h | 54 +++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Chips/Hisilicon/Hi6220/Include/Hi6220.h b/Chips/Hisilicon/Hi6220/Include/Hi6220.h index 203424a..248de00 100644 --- a/Chips/Hisilicon/Hi6220/Include/Hi6220.h +++ b/Chips/Hisilicon/Hi6220/Include/Hi6220.h @@ -23,6 +23,23 @@ #define HI6220_PERIPH_BASE 0xF4000000 #define HI6220_PERIPH_SZ 0x05800000 +#define GPIO4_CTRL_BASE 0xF7020000 +#define GPIO5_CTRL_BASE 0xF7021000 +#define GPIO6_CTRL_BASE 0xF7022000 +#define GPIO7_CTRL_BASE 0xF7023000 +#define GPIO8_CTRL_BASE 0xF7024000 +#define GPIO9_CTRL_BASE 0xF7025000 +#define GPIO10_CTRL_BASE 0xF7026000 +#define GPIO11_CTRL_BASE 0xF7027000 +#define GPIO12_CTRL_BASE 0xF7028000 +#define GPIO13_CTRL_BASE 0xF7029000 +#define GPIO14_CTRL_BASE 0xF702A000 +#define GPIO15_CTRL_BASE 0xF702B000 +#define GPIO16_CTRL_BASE 0xF702C000 +#define GPIO17_CTRL_BASE 0xF702D000 +#define GPIO18_CTRL_BASE 0xF702E000 +#define GPIO19_CTRL_BASE 0xF702F000 + #define PERI_CTRL_BASE 0xF7030000 #define SC_PERIPH_CTRL4 0x00C #define CTRL4_FPGA_EXT_PHY_SEL BIT3 @@ -45,18 +62,47 @@ #define SC_PERIPH_CTRL8 0x018 #define SC_PERIPH_CLKEN0 0x200 + +#define PERIPH_CLKEN0_USBOTG BIT4 + #define SC_PERIPH_CLKDIS0 0x204 #define SC_PERIPH_CLKSTAT0 0x208 +#define SC_PERIPH_CLKEN3 0x230 #define SC_PERIPH_RSTEN0 0x300 #define SC_PERIPH_RSTDIS0 0x304 #define SC_PERIPH_RSTSTAT0 0x308 +#define SC_PERIPH_RSTEN3 0x330 +#define SC_PERIPH_RSTDIS3 0x334 +#define SC_PERIPH_RSTSTAT3 0x338 #define RST0_USBOTG_BUS BIT4 #define RST0_POR_PICOPHY BIT5 #define RST0_USBOTG BIT6 #define RST0_USBOTG_32K BIT7 +/* SC_PERIPH_RSTEN0/RSTDIS0/RSTSTAT0 */ +#define PERIPH_RST0_MMC2 (1 << 2) + +/* SC_PERIPH_RSTEN3/RSTDIS3/RSTSTAT3 */ +#define PERIPH_RST3_CSSYS (1 << 0) +#define PERIPH_RST3_I2C0 (1 << 1) +#define PERIPH_RST3_I2C1 (1 << 2) +#define PERIPH_RST3_I2C2 (1 << 3) +#define PERIPH_RST3_I2C3 (1 << 4) +#define PERIPH_RST3_UART1 (1 << 5) +#define PERIPH_RST3_UART2 (1 << 6) +#define PERIPH_RST3_UART3 (1 << 7) +#define PERIPH_RST3_UART4 (1 << 8) +#define PERIPH_RST3_SSP (1 << 9) +#define PERIPH_RST3_PWM (1 << 10) +#define PERIPH_RST3_BLPWM (1 << 11) +#define PERIPH_RST3_TSENSOR (1 << 12) +#define PERIPH_RST3_DAPB (1 << 18) +#define PERIPH_RST3_HKADC (1 << 19) +#define PERIPH_RST3_CODEC_SSI (1 << 20) +#define PERIPH_RST3_PMUSSI1 (1 << 22) + #define EYE_PATTERN_PARA 0x7053348c #define MDDRC_AXI_BASE 0xF7120000 @@ -74,4 +120,12 @@ #define PMUSSI_BASE 0xF8000000 +#define PMUSSI_REG(x) (PMUSSI_BASE + ((x) << 2)) + +#define GPIO0_CTRL_BASE 0xF8011000 +#define GPIO1_CTRL_BASE 0xF8012000 +#define GPIO2_CTRL_BASE 0xF8013000 +#define GPIO3_CTRL_BASE 0xF8014000 + + #endif /* __HI6220_H__ */ From patchwork Wed Feb 15 14:54:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 94020 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp2064343qgi; Wed, 15 Feb 2017 06:56:31 -0800 (PST) X-Received: by 10.107.132.232 with SMTP id o101mr33026510ioi.4.1487170591260; Wed, 15 Feb 2017 06:56:31 -0800 (PST) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id 15si4217864iou.239.2017.02.15.06.56.30; Wed, 15 Feb 2017 06:56:31 -0800 (PST) Received-SPF: pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=linaro-uefi-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 9A46B607D4; Wed, 15 Feb 2017 14:56:30 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id F236F6072A; Wed, 15 Feb 2017 14:55:52 +0000 (UTC) X-Original-To: linaro-uefi@lists.linaro.org Delivered-To: linaro-uefi@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 443DC6074E; Wed, 15 Feb 2017 14:55:39 +0000 (UTC) Received: from mail-pf0-f169.google.com (mail-pf0-f169.google.com [209.85.192.169]) by lists.linaro.org (Postfix) with ESMTPS id 0A0E560EE7 for ; Wed, 15 Feb 2017 14:55:15 +0000 (UTC) Received: by mail-pf0-f169.google.com with SMTP id c73so28780711pfb.0 for ; Wed, 15 Feb 2017 06:55:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Ss3lcvWc/QctBxB5BibdfUzvBaQawkZ0lHmOpxvLVQw=; b=CQ6McSwpK6+2oNQOWBk5P2C6fgYlNxqcOf+OFOcewSie3n8onV7OU3IDTQo3ya/tIV 17yXInPS9x+RYbl267lImxX3rYrXjUfPXfIGxmv82SKq1S4MS4yX+xuN7DAf8gKzHe7e xAX5Z1EGVjhFg3DKWlVGx7BTVAPQWAJeI1tlgFY7VDu50hOGYJXwsM4eNUi0pYagtYUp CAbhL4W2Ty5kjNdXEfyH47Ezw8CURfA8F1Q6T0QrS4RZaUcajcyy/ZSbbzlX8rHCcsHH j/3Xz4aeGH2Kkv6M8W6Cf5k9e2JFt60RcAyhu47+jprh10vAr+M/y0Xx1lDadMC1vz31 glCg== X-Gm-Message-State: AMke39nPoUFoYTggYZtmrydNzY3QgQi8O3g1ifZmM7nCiuvaU4mfnEL7EFtCiT355uG8k/75zoM= X-Received: by 10.98.12.196 with SMTP id 65mr37480228pfm.40.1487170512394; Wed, 15 Feb 2017 06:55:12 -0800 (PST) Received: from localhost.localdomain ([45.56.159.211]) by smtp.gmail.com with ESMTPSA id s24sm8212782pgo.25.2017.02.15.06.55.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Feb 2017 06:55:11 -0800 (PST) From: Haojian Zhuang To: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org Date: Wed, 15 Feb 2017 22:54:56 +0800 Message-Id: <1487170499-22374-3-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> References: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> Subject: [Linaro-uefi] [PATCH v4 2/5] Drivers/Usb/DwUsb: support designware usb X-BeenThere: linaro-uefi@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-uefi-bounces@lists.linaro.org Sender: "Linaro-uefi" Support Designware USB controller. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang --- Drivers/Usb/DwUsbDxe/DwUsbDxe.c | 861 ++++++++++++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.dec | 45 ++ Drivers/Usb/DwUsbDxe/DwUsbDxe.h | 641 ++++++++++++++++++++++++++++ Drivers/Usb/DwUsbDxe/DwUsbDxe.inf | 52 +++ Include/Protocol/DwUsb.h | 81 ++++ 5 files changed, 1680 insertions(+) create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.c create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.dec create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.h create mode 100644 Drivers/Usb/DwUsbDxe/DwUsbDxe.inf create mode 100644 Include/Protocol/DwUsb.h diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.c b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c new file mode 100644 index 0000000..13b85b1 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.c @@ -0,0 +1,861 @@ +/** @file + + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "DwUsbDxe.h" + +#define USB_TYPE_LENGTH 16 +#define USB_BLOCK_HIGH_SPEED_SIZE 512 +#define DATA_SIZE 32768 +#define CMD_SIZE 512 +#define MATCH_CMD_LITERAL(Cmd, Buf) (!AsciiStrnCmp (Cmd, Buf, sizeof (Cmd) - 1)) + +// The time between interrupt polls, in units of 100 nanoseconds +// 10 Microseconds +#define DW_INTERRUPT_POLL_PERIOD 10000 + +#define ENDPOINT0 0 +#define ENDPOINT1 1 + +#define DIR_OUT 0 +#define DIR_IN 1 + +#define DWUSB_BUFFER_PAGE_NUM 16 + +#define DESCRIPTOR_INDEX_LANG 0 +#define DESCRIPTOR_INDEX_MANUFACTURER 1 +#define DESCRIPTOR_INDEX_PRODUCT 2 +#define DESCRIPTOR_INDEX_SERIALNUMBER 3 + +#define DESCRIPTOR_TYPE(x) (((x) >> 8) & 0xFF) +#define DESCRIPTOR_INDEX(x) ((x) & 0xFF) + +typedef struct { + USB_DEVICE_DESCRIPTOR *DeviceDescriptor; + USB_CONFIG_DESCRIPTOR *ConfigDescriptor; +} DW_USB_DESCRIPTOR; + +EFI_GUID gDwUsbProtocolGuid = DW_USB_PROTOCOL_GUID; + +STATIC DwUsbDevDmaDesc *gDmaDesc,*gDmaDescEp0,*gDmaDescIn; +STATIC USB_DEVICE_REQUEST *gCtrlReq; +STATIC VOID *RxBuf; +STATIC UINTN RxDescBytes; +STATIC UINTN mNumDataBytes; + +STATIC DW_USB_PROTOCOL *DwUsb; +STATIC DW_USB_DESCRIPTOR gDwUsbDescriptor; + +STATIC USB_DEVICE_RX_CALLBACK mDataReceivedCallback; +STATIC USB_DEVICE_TX_CALLBACK mDataSentCallback; + + +/* To detect which mode was run, high speed or full speed */ +STATIC +UINTN +UsbDrvPortSpeed ( + VOID + ) +{ + return (((READ_REG32 (DSTS) & DSTS_ENUMSPD_MASK) == DSTS_ENUMSPD_HIGH)); +} + +STATIC +VOID +ResetEndpoints ( + VOID + ) +{ + UINT32 Data; + + /* EP0 IN ACTIVE NEXT=1 */ + WRITE_REG32 (DIEPCTL0, DXEPCTL_USBACTEP | BIT11); + + /* EP0 OUT ACTIVE */ + WRITE_REG32 (DOEPCTL0, DXEPCTL_USBACTEP); + + /* Clear any pending OTG Interrupts */ + WRITE_REG32 (GOTGINT, ~0); + + /* Clear any pending interrupts */ + WRITE_REG32 (GINTSTS, ~0); + WRITE_REG32 (DIEPINT0, ~0); + WRITE_REG32 (DOEPINT0, ~0); + WRITE_REG32 (DIEPINT1, ~0); + WRITE_REG32 (DOEPINT1, ~0); + + /* IN EP interrupt mask */ + WRITE_REG32 (DIEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK); + /* OUT EP interrupt mask */ + WRITE_REG32 (DOEPMSK, DXEPMSK_TIMEOUTMSK | DXEPMSK_AHBERMSK | DXEPMSK_XFERCOMPLMSK); + /* Enable interrupts on EndPoint0 */ + WRITE_REG32 (DAINTMSK, (1 << DAINTMSK_OUTEPMSK_SHIFT) | (1 << DAINTMSK_INEPMSK_SHIFT)); + + /* EP0 OUT Transfer Size:64 Bytes, 1 Packet, 3 Setup Packet, Read to receive setup packet*/ + WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64)); + + //notes that:the compulsive conversion is expectable. + gDmaDescEp0->status.b.bs = 0x3; + gDmaDescEp0->status.b.mtrf = 0; + gDmaDescEp0->status.b.sr = 0; + gDmaDescEp0->status.b.l = 1; + gDmaDescEp0->status.b.ioc = 1; + gDmaDescEp0->status.b.sp = 0; + gDmaDescEp0->status.b.bytes = 64; + gDmaDescEp0->buf = (UINT32)(UINTN)gCtrlReq; + gDmaDescEp0->status.b.sts = 0; + gDmaDescEp0->status.b.bs = 0x0; + WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)gDmaDescEp0); + /* EP0 OUT ENABLE CLEARNAK */ + Data = READ_REG32 (DOEPCTL0); + WRITE_REG32 (DOEPCTL0, Data | DXEPCTL_EPENA | DXEPCTL_CNAK); +} + +STATIC +VOID +EndPointTx ( + IN UINT8 EndPoint, + IN CONST VOID *Ptr, + IN UINTN Len + ) +{ + UINT32 BlockSize; + UINT32 Packets; + UINT32 Data; + + /* EPx OUT ACTIVE */ + Data = READ_REG32 (DIEPCTL (EndPoint)); + WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_USBACTEP); + if (!EndPoint) { + BlockSize = 64; + } else { + BlockSize = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : 64; + } + Packets = (Len + BlockSize - 1) / BlockSize; + + if (!Len) { + /* send one empty packet */ + gDmaDescIn->status.b.bs = 0x3; + gDmaDescIn->status.b.l = 1; + gDmaDescIn->status.b.ioc = 1; + gDmaDescIn->status.b.sp = 1; + gDmaDescIn->status.b.bytes = 0; + gDmaDescIn->buf = 0; + gDmaDescIn->status.b.sts = 0; + gDmaDescIn->status.b.bs = 0x0; + + WRITE_REG32 (DIEPDMA (EndPoint), (UINT32)(UINTN)gDmaDescIn); // DMA Address (DMAAddr) is zero + } else { + WRITE_REG32 (DIEPTSIZ (EndPoint), Len | DXEPTSIZN_PKTCNT (Packets)); + + //flush cache + WriteBackDataCacheRange ((VOID *)Ptr, Len); + + gDmaDescIn->status.b.bs = 0x3; + gDmaDescIn->status.b.l = 1; + gDmaDescIn->status.b.ioc = 1; + gDmaDescIn->status.b.sp = 1; + gDmaDescIn->status.b.bytes = Len; + gDmaDescIn->buf = (UINT32)(UINTN)Ptr; + gDmaDescIn->status.b.sts = 0; + gDmaDescIn->status.b.bs = 0x0; + WRITE_REG32 (DIEPDMA (EndPoint), (UINT32)(UINTN)gDmaDescIn); // Ptr is DMA address + } + ArmDataSynchronizationBarrier (); + /* epena & cnak */ + Data = READ_REG32 (DIEPCTL (EndPoint)); + WRITE_REG32 (DIEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK | BIT11); +} + +STATIC +VOID +EndPointRx ( + IN UINTN EndPoint, + IN UINTN Len + ) +{ + UINT32 Data; + + /* EPx UNSTALL */ + Data = READ_REG32 (DOEPCTL (EndPoint)); + WRITE_REG32 (DOEPCTL (EndPoint), Data & ~DXEPCTL_STALL); + /* EPx OUT ACTIVE */ + Data = READ_REG32 (DOEPCTL (EndPoint)); + WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_USBACTEP); + + if (Len >= DATA_SIZE) { + RxDescBytes = DATA_SIZE; + } else { + RxDescBytes = Len; + } + + RxBuf = AllocatePool (DATA_SIZE); + if (RxBuf == NULL) { + DEBUG ((DEBUG_ERROR, "EndPointRx: failed to allocate buffer\n")); + return; + } + + InvalidateDataCacheRange (RxBuf, Len); + + gDmaDesc->status.b.bs = 0x3; + gDmaDesc->status.b.mtrf = 0; + gDmaDesc->status.b.sr = 0; + gDmaDesc->status.b.l = 1; + gDmaDesc->status.b.ioc = 1; + gDmaDesc->status.b.sp = 0; + gDmaDesc->status.b.bytes = (UINT32)RxDescBytes; + gDmaDesc->buf = (UINT32)(UINTN)RxBuf; + gDmaDesc->status.b.sts = 0; + gDmaDesc->status.b.bs = 0x0; + + ArmDataSynchronizationBarrier (); + WRITE_REG32 (DOEPDMA (EndPoint), (UINT32)(UINTN)gDmaDesc); + /* EPx OUT ENABLE CLEARNAK */ + Data = READ_REG32 (DOEPCTL (EndPoint)); + WRITE_REG32 (DOEPCTL (EndPoint), Data | DXEPCTL_EPENA | DXEPCTL_CNAK); +} + +STATIC +EFI_STATUS +HandleGetDescriptor ( + IN USB_DEVICE_REQUEST *Request + ) +{ + UINTN ResponseSize; + VOID *ResponseData; + EFI_USB_STRING_DESCRIPTOR *Descriptor = NULL; + UINTN DescriptorSize; + + ResponseSize = 0; + ResponseData = NULL; + + // Pretty confused if bmRequestType is anything but this: + if (Request->RequestType != USB_DEV_GET_DESCRIPTOR_REQ_TYPE) { + return EFI_INVALID_PARAMETER; + } + + // Choose the response + switch (DESCRIPTOR_TYPE(Request->Value)) { + case USB_DESC_TYPE_DEVICE: + DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for device descriptor\n")); + ResponseSize = sizeof (USB_DEVICE_DESCRIPTOR); + ResponseData = gDwUsbDescriptor.DeviceDescriptor; + break; + case USB_DESC_TYPE_CONFIG: + DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for config descriptor\n")); + ResponseSize = gDwUsbDescriptor.ConfigDescriptor->TotalLength; + ResponseData = gDwUsbDescriptor.ConfigDescriptor; + break; + case USB_DESC_TYPE_STRING: + DEBUG ((DEBUG_INFO, "DwUsbDxe: Got a request for String descriptor %d\n", Request->Value & 0xFF)); + switch (DESCRIPTOR_INDEX(Request->Value)) { + case 0: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + (LANG_LENGTH + 1) * sizeof (CHAR16); + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + if (Descriptor == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Descriptor->Length = LANG_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetLang (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + case 1: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + (MANU_FACTURER_STRING_LENGTH + 1) * sizeof (CHAR16); + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + if (Descriptor == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Descriptor->Length = MANU_FACTURER_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetManuFacturer (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + case 2: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + (PRODUCT_STRING_LENGTH + 1) * sizeof (CHAR16); + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + if (Descriptor == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Descriptor->Length = PRODUCT_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetProduct (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + case 3: + DescriptorSize = sizeof (EFI_USB_STRING_DESCRIPTOR) + + SERIAL_STRING_LENGTH * sizeof (CHAR16) + 1; + Descriptor = (EFI_USB_STRING_DESCRIPTOR *)AllocateZeroPool (DescriptorSize); + if (Descriptor == NULL) { + return EFI_OUT_OF_RESOURCES; + } + Descriptor->Length = SERIAL_STRING_LENGTH * sizeof (CHAR16); + Descriptor->DescriptorType = USB_DESC_TYPE_STRING; + DwUsb->GetSerialNo (Descriptor->String, &Descriptor->Length); + ResponseSize = Descriptor->Length; + ResponseData = Descriptor; + break; + } + break; + default: + DEBUG ((DEBUG_INFO, "DwUsbDxe: Didn't understand request for descriptor 0x%04x\n", Request->Value)); + return EFI_INVALID_PARAMETER; + } + + // Send the response + if (Request->Length < ResponseSize) { + // Truncate response + ResponseSize = Request->Length; + } else if (Request->Length > ResponseSize) { + DEBUG ((DEBUG_INFO, "DwUsbDxe: Info: ResponseSize < wLength\n")); + } + + EndPointTx (ENDPOINT0, ResponseData, ResponseSize); + if (Descriptor) { + FreePool (Descriptor); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HandleSetAddress ( + IN USB_DEVICE_REQUEST *Request + ) +{ + UINT32 Data; + + // Pretty confused if bmRequestType is anything but this: + if (Request->RequestType != USB_DEV_SET_ADDRESS_REQ_TYPE) { + return EFI_INVALID_PARAMETER; + } + DEBUG ((DEBUG_INFO, "DwUsbDxe: Setting address to %d\n", Request->Value)); + ResetEndpoints (); + + Data = READ_REG32 (DCFG); + Data &= ~DCFG_DEVADDR_MASK; + Data |= DCFG_DEVADDR (Request->Value); + WRITE_REG32 (DCFG, Data); + EndPointTx (ENDPOINT0, NULL, 0); + + return EFI_SUCCESS; +} + +STATIC +VOID +UsbDrvRequestEndpoint ( + IN UINTN Type, + IN UINTN Dir + ) +{ + UINTN EndPoint = 1; + UINTN NewBits; + UINT32 Data; + + NewBits = DXEPCTL_EPTYPE (Type) | BIT28; + + /* + * (Type << 18):Endpoint Type (EPType) + * 0x10000000:Endpoint Enable (EPEna) + * 0x000C000:Endpoint Type (EPType);Hardcoded to 00 for control. + * (ep<<22):TxFIFO Number (TxFNum) + * 0x20000:NAK Status (NAKSts);The core is transmitting NAK handshakes on this endpoint. + */ + if (Dir == DIR_IN) { // IN: to host + Data = READ_REG32 (DIEPCTL (EndPoint)); + Data &= ~DXEPCTL_EPTYPE_MASK; + Data |= NewBits | DXEPCTL_TXFNUM (EndPoint) | DXEPCTL_NAKSTS; + WRITE_REG32 (DIEPCTL (EndPoint), Data); + } else { // OUT: to device + Data = READ_REG32 (DOEPCTL (EndPoint)); + Data &= ~DXEPCTL_EPTYPE_MASK; + Data |= NewBits; + WRITE_REG32 (DOEPCTL (EndPoint), Data); + } +} + +STATIC +EFI_STATUS +HandleSetConfiguration ( + IN USB_DEVICE_REQUEST *Request + ) +{ + UINT32 Data; + + if (Request->RequestType != USB_DEV_SET_CONFIGURATION_REQ_TYPE) { + return EFI_INVALID_PARAMETER; + } + + // Cancel all transfers + ResetEndpoints (); + + UsbDrvRequestEndpoint (2, DIR_OUT); + UsbDrvRequestEndpoint (2, DIR_IN); + + Data = READ_REG32 (DIEPCTL1); + WRITE_REG32 (DIEPCTL1, Data | BIT28 | BIT19 | DXEPCTL_USBACTEP | BIT11); + + /* Enable interrupts on all endpoints */ + WRITE_REG32 (DAINTMSK, ~0); + + EndPointRx (ENDPOINT1, CMD_SIZE); + EndPointTx (ENDPOINT0, NULL, 0); + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +HandleDeviceRequest ( + IN USB_DEVICE_REQUEST *Request + ) +{ + EFI_STATUS Status; + + switch (Request->Request) { + case USB_DEV_GET_DESCRIPTOR: + Status = HandleGetDescriptor (Request); + break; + case USB_DEV_SET_ADDRESS: + Status = HandleSetAddress (Request); + break; + case USB_DEV_SET_CONFIGURATION: + Status = HandleSetConfiguration (Request); + break; + default: + DEBUG ((DEBUG_ERROR, + "Didn't understand RequestType 0x%x Request 0x%x\n", + Request->RequestType, Request->Request)); + Status = EFI_INVALID_PARAMETER; + break; + } + + return Status; +} + +STATIC +VOID +HandleEndPointInEvent ( + VOID + ) +{ + UINT32 EndPointInts; + + EndPointInts = READ_REG32 (DIEPINT0); + WRITE_REG32 (DIEPINT0, EndPointInts); + if (EndPointInts & DXEPINT_XFERCOMPL) { + DEBUG ((DEBUG_INFO, "INT: IN TX completed.DIEPTSIZ (0) = 0x%x.\n", READ_REG32 (DIEPTSIZ0))); + } + + EndPointInts = READ_REG32 (DIEPINT1); + WRITE_REG32 (DIEPINT1, EndPointInts); + if (EndPointInts & DXEPINT_XFERCOMPL) { + DEBUG ((DEBUG_INFO, "ep1: IN TX completed\n")); + } +} + +STATIC +VOID +HandleEndPointOutEvent ( + VOID + ) +{ + UINT32 EndPointInts; + UINT32 Data; + + /* indicates the status of an endpoint + * with respect to USB- and AHB-related events. */ + EndPointInts = READ_REG32 (DOEPINT0); + if (EndPointInts) { + WRITE_REG32 (DOEPINT0, EndPointInts); + if (EndPointInts & DXEPINT_XFERCOMPL) { + DEBUG ((DEBUG_INFO, "INT: EP0 RX completed. DOEPTSIZ(0) = 0x%x.\n", READ_REG32 (DOEPTSIZ0))); + } + /* + * + IN Token Received When TxFIFO is Empty (INTknTXFEmp) + * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic) + * was empty. This interrupt is asserted on the endpoint for which the IN token + * was received. + */ + if (EndPointInts & BIT3) { /* SETUP phase done */ + Data = READ_REG32 (DIEPCTL0) | DXEPCTL_SNAK; + WRITE_REG32 (DIEPCTL0, Data); + Data = READ_REG32 (DOEPCTL0) | DXEPCTL_SNAK; + WRITE_REG32 (DOEPCTL0, Data); + /*clear IN EP intr*/ + WRITE_REG32 (DIEPINT0, ~0); + HandleDeviceRequest((USB_DEVICE_REQUEST *)gCtrlReq); + } + + /* Make sure EP0 OUT is set up to accept the next request */ + WRITE_REG32 (DOEPTSIZ0, DXEPTSIZ_SUPCNT(3) | DXEPTSIZ_PKTCNT(1) | DXEPTSIZ_XFERSIZE(64)); + /* + * IN Token Received When TxFIFO is Empty (INTknTXFEmp) + * Indicates that an IN token was received when the associated TxFIFO (periodic/nonperiodic) + * was empty. This interrupt is asserted on the endpoint for which the IN token + * was received. + */ + gDmaDescEp0->status.b.bs = 0x3; + gDmaDescEp0->status.b.mtrf = 0; + gDmaDescEp0->status.b.sr = 0; + gDmaDescEp0->status.b.l = 1; + gDmaDescEp0->status.b.ioc = 1; + gDmaDescEp0->status.b.sp = 0; + gDmaDescEp0->status.b.bytes = 64; + gDmaDescEp0->buf = (UINT32)(UINTN)gCtrlReq; + gDmaDescEp0->status.b.sts = 0; + gDmaDescEp0->status.b.bs = 0x0; + WRITE_REG32 (DOEPDMA0, (UINT32)(UINTN)gDmaDescEp0); + // endpoint enable; clear NAK + WRITE_REG32 (DOEPCTL0, DXEPCTL_EPENA | DXEPCTL_CNAK); + } + + EndPointInts = (READ_REG32 (DOEPINT1)); + if (EndPointInts) { + WRITE_REG32 (DOEPINT1, EndPointInts); + /* Transfer Completed Interrupt (XferCompl);Transfer completed */ + if (EndPointInts & DXEPINT_XFERCOMPL) { + + UINTN Bytes = RxDescBytes - gDmaDesc->status.b.bytes; + UINTN Len = 0; + + ArmDataSynchronizationBarrier (); + if (MATCH_CMD_LITERAL ("download", RxBuf)) { + mNumDataBytes = AsciiStrHexToUint64 (RxBuf + sizeof ("download")); + } else { + if (mNumDataBytes != 0) { + mNumDataBytes -= Bytes; + } + } + + mDataReceivedCallback (Bytes, RxBuf); + + if (mNumDataBytes == 0) { + Len = CMD_SIZE; + } else if (mNumDataBytes > DATA_SIZE) { + Len = DATA_SIZE; + } else { + Len = mNumDataBytes; + } + + EndPointRx (ENDPOINT1, Len); + } + } +} + +// Instead of actually registering interrupt handlers, we poll the controller's +// interrupt source register in this function. +STATIC +VOID +CheckInterrupts ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + UINT32 Ints; + UINT32 Data; + + + // interrupt register + Ints = READ_REG32 (GINTSTS); + + /* + * bus reset + * The core sets this bit to indicate that a reset is detected on the USB. + */ + if (Ints & GINTSTS_USBRST) { + WRITE_REG32 (DCFG, DCFG_DESCDMA | DCFG_NZ_STS_OUT_HSHK); + ResetEndpoints (); + } + + /* + * enumeration done, we now know the speed + * The core sets this bit to indicate that speed enumeration is complete. The + * application must read the Device Status (DSTS) register to obtain the + * enumerated speed. + */ + if (Ints & GINTSTS_ENUMDONE) { + /* Set up the maximum packet sizes accordingly */ + UINTN MaxPacket = UsbDrvPortSpeed () ? USB_BLOCK_HIGH_SPEED_SIZE : MAX_PACKET_SIZE_CONTROL; + //Set Maximum In Packet Size (MPS) + Data = READ_REG32 (DIEPCTL1); + Data &= ~DXEPCTL_MPS_MASK; + Data |= MaxPacket; + WRITE_REG32 (DIEPCTL1, Data); + //Set Maximum Out Packet Size (MPS) + Data = READ_REG32 (DOEPCTL1); + Data &= ~DXEPCTL_MPS_MASK; + Data |= MaxPacket; + WRITE_REG32 (DOEPCTL1, Data); + } + + /* + * IN EP event + * The core sets this bit to indicate that an interrupt is pending on one of the IN + * endpoInts of the core (in Device mode). The application must read the + * Device All EndpoInts Interrupt (DAINT) register to determine the exact + * number of the IN endpoint on which the interrupt occurred, and then read + * the corresponding Device IN Endpoint-n Interrupt (DIEPINTn) register to + * determine the exact cause of the interrupt. The application must clear the + * appropriate status bit in the corresponding DIEPINTn register to clear this bit. + */ + if (Ints & GINTSTS_IEPINT) { + HandleEndPointInEvent (); + } + + /* + * OUT EP event + * The core sets this bit to indicate that an interrupt is pending on one of the + * OUT endpoints of the core (in Device mode). The application must read the + * Device All EndpoInts Interrupt (DAINT) register to determine the exact + * number of the OUT endpoint on which the interrupt occurred, and then read + * the corresponding Device OUT Endpoint-n Interrupt (DOEPINTn) register + * to determine the exact cause of the interrupt. The application must clear the + * appropriate status bit in the corresponding DOEPINTn register to clear this bit. + */ + if (Ints & GINTSTS_OEPINT) { + HandleEndPointOutEvent (); + } + + // clear ints + WRITE_REG32 (GINTSTS, Ints); +} + +EFI_STATUS +DwUsbSend ( + IN UINT8 EndpointIndex, + IN UINTN Size, + IN CONST VOID *Buffer + ) +{ + EndPointTx (EndpointIndex, Buffer, Size); + return EFI_SUCCESS; +} + +STATIC +VOID +DwUsbInit ( + VOID + ) +{ + VOID *Buf; + UINT32 Data; + + Buf = UncachedAllocatePages (DWUSB_BUFFER_PAGE_NUM); + gDmaDesc = Buf; + gDmaDescEp0 = gDmaDesc + sizeof (DwUsbDevDmaDesc); + gDmaDescIn = gDmaDescEp0 + sizeof (DwUsbDevDmaDesc); + gCtrlReq = (USB_DEVICE_REQUEST *)gDmaDescIn + sizeof (DwUsbDevDmaDesc); + + ZeroMem (Buf, EFI_PAGE_SIZE * DWUSB_BUFFER_PAGE_NUM); + + /*Reset usb controller.*/ + /* Wait for OTG AHB master idle */ + do { + Data = READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE; + } while (Data == 0); + + /* OTG: Assert Software Reset */ + WRITE_REG32 (GRSTCTL, GRSTCTL_CSFTRST); + + /* Wait for OTG to ack reset */ + while ((READ_REG32 (GRSTCTL) & GRSTCTL_CSFTRST) == GRSTCTL_CSFTRST); + + /* Wait for OTG AHB master idle */ + while ((READ_REG32 (GRSTCTL) & GRSTCTL_AHBIDLE) == 0); + + WRITE_REG32 (GDFIFOCFG, DATA_FIFO_CONFIG); + WRITE_REG32 (GRXFSIZ, RX_SIZE); + WRITE_REG32 (GNPTXFSIZ, ENDPOINT_TX_SIZE); + WRITE_REG32 (DIEPTXF1, DATA_IN_ENDPOINT_TX_FIFO1); + WRITE_REG32 (DIEPTXF2, DATA_IN_ENDPOINT_TX_FIFO2); + WRITE_REG32 (DIEPTXF3, DATA_IN_ENDPOINT_TX_FIFO3); + WRITE_REG32 (DIEPTXF4, DATA_IN_ENDPOINT_TX_FIFO4); + WRITE_REG32 (DIEPTXF5, DATA_IN_ENDPOINT_TX_FIFO5); + WRITE_REG32 (DIEPTXF6, DATA_IN_ENDPOINT_TX_FIFO6); + WRITE_REG32 (DIEPTXF7, DATA_IN_ENDPOINT_TX_FIFO7); + WRITE_REG32 (DIEPTXF8, DATA_IN_ENDPOINT_TX_FIFO8); + WRITE_REG32 (DIEPTXF9, DATA_IN_ENDPOINT_TX_FIFO9); + WRITE_REG32 (DIEPTXF10, DATA_IN_ENDPOINT_TX_FIFO10); + WRITE_REG32 (DIEPTXF11, DATA_IN_ENDPOINT_TX_FIFO11); + WRITE_REG32 (DIEPTXF12, DATA_IN_ENDPOINT_TX_FIFO12); + WRITE_REG32 (DIEPTXF13, DATA_IN_ENDPOINT_TX_FIFO13); + WRITE_REG32 (DIEPTXF14, DATA_IN_ENDPOINT_TX_FIFO14); + WRITE_REG32 (DIEPTXF15, DATA_IN_ENDPOINT_TX_FIFO15); + + /* + * set Periodic TxFIFO Empty Level, + * Non-Periodic TxFIFO Empty Level, + * Enable DMA, Unmask Global Intr + */ + WRITE_REG32 (GAHBCFG, GAHBCFG_CTRL_MASK); + + /*select 8bit UTMI+, ULPI Inerface*/ + WRITE_REG32 (GUSBCFG, GUSBCFG_USBTRDTIM_8BIT); + + /* Detect usb work mode,host or device? */ + do { + Data = READ_REG32 (GINTSTS); + } while (Data & GINTSTS_CURMODE_HOST); + + /*Init global and device mode csr register.*/ + /*set Non-Zero-Length status out handshake */ + Data = (0x20 << DCFG_EPMISCNT_SHIFT) | DCFG_NZ_STS_OUT_HSHK; + WRITE_REG32 (DCFG, Data); + + /* Interrupt unmask: IN event, OUT event, bus reset */ + Data = GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_ENUMDONE | GINTSTS_USBRST; + WRITE_REG32 (GINTMSK, Data); + + do { + Data = READ_REG32 (GINTSTS) & GINTSTS_ENUMDONE; + } while (Data); + + /* Clear any pending OTG Interrupts */ + WRITE_REG32 (GOTGINT, ~0); + /* Clear any pending interrupts */ + WRITE_REG32 (GINTSTS, ~0); + WRITE_REG32 (GINTMSK, ~0); + Data = READ_REG32 (GOTGINT); + Data &= ~0x3000; // unknown reserved bits + WRITE_REG32 (GOTGINT, Data); + + /* endpoint settings cfg */ + ResetEndpoints (); + /* wait for stable */ + MicroSecondDelay (1); + + /* init finish. and ready to transfer data */ + + /* Soft Disconnect */ + WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE | DCTL_SFTDISCON); + /* wait for stable */ + MicroSecondDelay (10000); + + /* Soft Reconnect */ + WRITE_REG32 (DCTL, DCTL_PWRONPRGDONE); +} + +EFI_STATUS +EFIAPI +DwUsbStart ( + IN USB_DEVICE_DESCRIPTOR *DeviceDescriptor, + IN VOID **Descriptors, + IN USB_DEVICE_RX_CALLBACK RxCallback, + IN USB_DEVICE_TX_CALLBACK TxCallback + ) +{ + EFI_STATUS Status; + EFI_EVENT TimerEvent; + + if ((DeviceDescriptor == NULL) || + (Descriptors[0] == NULL) || + (RxCallback == NULL) || + (TxCallback == NULL)) { + return EFI_INVALID_PARAMETER; + } + + DwUsbInit(); + + gDwUsbDescriptor.DeviceDescriptor = DeviceDescriptor; + // Right now we just support one configuration + ASSERT (gDwUsbDescriptor.DeviceDescriptor->NumConfigurations == 1); + gDwUsbDescriptor.DeviceDescriptor->StrManufacturer = DESCRIPTOR_INDEX_MANUFACTURER; + gDwUsbDescriptor.DeviceDescriptor->StrProduct = DESCRIPTOR_INDEX_PRODUCT; + gDwUsbDescriptor.DeviceDescriptor->StrSerialNumber = DESCRIPTOR_INDEX_SERIALNUMBER; + // ... and one interface + gDwUsbDescriptor.ConfigDescriptor = (USB_CONFIG_DESCRIPTOR *)Descriptors[0]; + ASSERT (gDwUsbDescriptor.ConfigDescriptor->NumInterfaces == 1); + + mDataReceivedCallback = RxCallback; + mDataSentCallback = TxCallback; + + // Register a timer event so CheckInterupts gets called periodically + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + CheckInterrupts, + NULL, + &TimerEvent + ); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + TimerEvent, + TimerPeriodic, + DW_INTERRUPT_POLL_PERIOD + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +USB_DEVICE_PROTOCOL mUsbDevice = { + DwUsbStart, + DwUsbSend +}; + + +EFI_STATUS +EFIAPI +DwUsbEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gDwUsbProtocolGuid, NULL, (VOID **) &DwUsb); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = DwUsb->PhyInit(USB_DEVICE_MODE); + if (EFI_ERROR (Status)) { + return Status; + } + + return gBS->InstallProtocolInterface ( + &ImageHandle, + &gUsbDeviceProtocolGuid, + EFI_NATIVE_INTERFACE, + &mUsbDevice + ); +} diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec new file mode 100644 index 0000000..d986798 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec @@ -0,0 +1,45 @@ +#/** @file +# Framework Module Development Environment Industry Standards +# +# This Package provides headers and libraries that conform to EFI/PI Industry standards. +# Copyright (c) 2007, Intel Corporation. All rights reserved.
+# Copyright (c) 2012-2014, ARM Ltd. All rights reserved.
+# Copyright (c) 2015-2017, Linaro. All rights reserved.
+# +# This program and the accompanying materials are licensed and made available under +# the terms and conditions of the BSD License which accompanies this distribution. +# The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#**/ + +[Defines] + DEC_SPECIFICATION = 0x00010019 + PACKAGE_NAME = DwUsbDxePkg + PACKAGE_GUID = 114a3be9-10f7-4bf1-81ca-09ac52d4c3d5 + PACKAGE_VERSION = 0.1 + + +################################################################################ +# +# Include Section - list of Include Paths that are provided by this package. +# Comments are used for Keywords and Module Types. +# +# Supported Module Types: +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION +# +################################################################################ + +[Guids.common] + gDwUsbDxeTokenSpaceGuid = { 0x131c4d02, 0x9449, 0x4ee9, { 0xba, 0x3d, 0x69, 0x50, 0x21, 0x89, 0x26, 0x0b }} + +[Protocols.common] + gDwUsbProtocolGuid = { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} + +[PcdsFixedAtBuild.common] + # DwUsb Driver PCDs + gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress|0x0|UINT32|0x00000001 + gDwUsbDxeTokenSpaceGuid.PcdSysCtrlBaseAddress|0x0|UINT32|0x00000002 diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.h b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h new file mode 100644 index 0000000..775d5b3 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.h @@ -0,0 +1,641 @@ +/** @file + + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DW_USB_DXE_H__ +#define __DW_USB_DXE_H__ + +#define DW_USB_BASE FixedPcdGet32 (PcdDwUsbDxeBaseAddress) + +#define READ_REG32(Offset) MmioRead32 (DW_USB_BASE + Offset) +#define READ_REG16(Offset) (UINT16)READ_REG32 (Offset) +#define WRITE_REG32(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, Val) +#define WRITE_REG16(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val) +#define WRITE_REG8(Offset, Val) MmioWrite32 (DW_USB_BASE + Offset, (UINT32) Val) + +// Max packet size in bytes (For Full Speed USB 64 is the only valid value) +#define MAX_PACKET_SIZE_CONTROL 64 + +#define MAX_PACKET_SIZE_BULK 512 + +// 8 Endpoints, in and out. Don't count the Endpoint 0 setup buffer +#define DW_NUM_ENDPOINTS 16 + +// Endpoint Indexes +#define DW_EP0SETUP 0x20 +#define DW_EP0RX 0x00 +#define DW_EP0TX 0x01 +#define DW_EP1RX 0x02 +#define DW_EP1TX 0x03 + +// DcInterrupt bits +#define DW_DC_INTERRUPT_EP1TX BIT13 +#define DW_DC_INTERRUPT_EP1RX BIT12 +#define DW_DC_INTERRUPT_EP0TX BIT11 +#define DW_DC_INTERRUPT_EP0RX BIT10 +#define DW_DC_INTERRUPT_EP0SETUP BIT8 +#define DW_DC_INTERRUPT_VBUS BIT7 +#define DW_DC_INTERRUPT_DMA BIT6 +#define DW_DC_INTERRUPT_HS_STAT BIT5 +#define DW_DC_INTERRUPT_RESUME BIT4 +#define DW_DC_INTERRUPT_SUSP BIT3 +#define DW_DC_INTERRUPT_PSOF BIT2 +#define DW_DC_INTERRUPT_SOF BIT1 +#define DW_DC_INTERRUPT_BRESET BIT0 +// All valid peripheral controller int rrupts +#define DW_DC_INTERRUPT_MASK 0x003FFFDFF + +#define DW_ADDRESS 0x200 +#define DW_ADDRESS_DEVEN BIT7 + +#define DW_MODE 0x20C +#define DW_MODE_DATA_BUS_WIDTH BIT8 +#define DW_MODE_CLKAON BIT7 +#define DW_MODE_SFRESET BIT4 +#define DW_MODE_WKUPCS BIT2 + +#define DW_ENDPOINT_MAX_PACKET_SIZE 0x204 + +#define DW_ENDPOINT_TYPE 0x208 +#define DW_ENDPOINT_TYPE_NOEMPKT BIT4 +#define DW_ENDPOINT_TYPE_ENABLE BIT3 + +#define DW_INTERRUPT_CONFIG 0x210 +// Interrupt config value to only interrupt on ACK of IN and OUT tokens +#define DW_INTERRUPT_CONFIG_ACK_ONLY (BIT2 | BIT5 | BIT6) + +#define DW_DC_INTERRUPT 0x218 +#define DW_DC_INTERRUPT_ENABLE 0x214 + +#define DW_CTRL_FUNCTION 0x228 +#define DW_CTRL_FUNCTION_VENDP BIT3 +#define DW_CTRL_FUNCTION_DSEN BIT2 +#define DW_CTRL_FUNCTION_STATUS BIT1 + +#define DW_DEVICE_UNLOCK 0x27C +#define DW_DEVICE_UNLOCK_MAGIC 0xAA37 + +#define DW_SW_RESET_REG 0x30C +#define DW_SW_RESET_ALL BIT0 + +#define DW_DEVICE_ID 0x370 + +#define DW_OTG_CTRL_SET 0x374 +#define DW_OTG_CTRL_CLR (OTG_CTRL_SET + 2) +#define DW_OTG_CTRL_OTG_DISABLE BIT10 +#define DW_OTG_CTRL_VBUS_CHRG BIT6 +#define DW_OTG_CTRL_VBUS_DISCHRG BIT5 +#define DW_OTG_CTRL_DM_PULLDOWN BIT2 +#define DW_OTG_CTRL_DP_PULLDOWN BIT1 +#define DW_OTG_CTRL_DP_PULLUP BIT0 + +#define DW_OTG_STATUS 0x378 +#define DW_OTG_STATUS_B_SESS_END BIT7 +#define DW_OTG_STATUS_A_B_SESS_VLD BIT1 + +#define DW_OTG_INTERRUPT_LATCH_SET 0x37C +#define DW_OTG_INTERRUPT_LATCH_CLR 0x37E +#define DW_OTG_INTERRUPT_ENABLE_RISE 0x384 + +#define DW_DMA_ENDPOINT_INDEX 0x258 + +#define DW_ENDPOINT_INDEX 0x22c +#define DW_DATA_PORT 0x220 +#define DW_BUFFER_LENGTH 0x21c + +// Device ID Values +#define PHILLIPS_VENDOR_ID_VAL 0x04cc +#define DW_PRODUCT_ID_VAL 0x1761 +#define DW_DEVICE_ID_VAL ((ISP1761_PRODUCT_ID_VAL << 16) | \ + PHILLIPS_VENDOR_ID_VAL) + +#define DWC_OTG_BASE DW_USB_BASE + +#define USB_NUM_ENDPOINTS 2 +#define MAX_EPS_CHANNELS 16 + +#define BULK_OUT_EP 1 +#define BULK_IN_EP 1 + +#define RX_REQ_LEN 512 +#define MAX_PACKET_LEN 512 + +#define DATA_FIFO_CONFIG 0x0F801000 +/* RX FIFO: 2048 bytes */ +#define RX_SIZE 0x00000200 +/* Non-periodic TX FIFO: 128 bytes. start address: 0x200 * 4. */ +#define ENDPOINT_TX_SIZE 0x01000200 + +/* EP1 TX FIFO: 1024 bytes. start address: 0x220 * 4. */ +/* EP2 TX FIFO: 1024 bytes. start address: 0x320 * 4. */ +/* EP3 TX FIFO: 1024 bytes. start address: 0x420 * 4. */ +/* EP4 TX FIFO: 1024 bytes. start address: 0x520 * 4. */ +/* EP5 TX FIFO: 128 bytes. start address: 0x620 * 4. */ +/* EP6 TX FIFO: 128 bytes. start address: 0x640 * 4. */ +/* EP7 TX FIFO: 128 bytes. start address: 0x660 * 4. */ +/* EP8 TX FIFO: 128 bytes. start address: 0x680 * 4. */ +/* EP9 TX FIFO: 128 bytes. start address: 0x6A0 * 4. */ +/* EP10 TX FIFO: 128 bytes. start address: 0x6C0 * 4. */ +/* EP11 TX FIFO: 128 bytes. start address: 0x6E0 * 4. */ +/* EP12 TX FIFO: 128 bytes. start address: 0x700 * 4. */ +/* EP13 TX FIFO: 128 bytes. start address: 0x720 * 4. */ +/* EP14 TX FIFO: 128 bytes. start address: 0x740 * 4. */ +/* EP15 TX FIFO: 128 bytes. start address: 0x760 * 4. */ + +#define DATA_IN_ENDPOINT_TX_FIFO1 0x01000220 +#define DATA_IN_ENDPOINT_TX_FIFO2 0x01000320 +#define DATA_IN_ENDPOINT_TX_FIFO3 0x01000420 +#define DATA_IN_ENDPOINT_TX_FIFO4 0x01000520 +#define DATA_IN_ENDPOINT_TX_FIFO5 0x00200620 +#define DATA_IN_ENDPOINT_TX_FIFO6 0x00200640 +#define DATA_IN_ENDPOINT_TX_FIFO7 0x00200680 +#define DATA_IN_ENDPOINT_TX_FIFO8 0x002006A0 +#define DATA_IN_ENDPOINT_TX_FIFO9 0x002006C0 +#define DATA_IN_ENDPOINT_TX_FIFO10 0x002006E0 +#define DATA_IN_ENDPOINT_TX_FIFO11 0x00200700 +#define DATA_IN_ENDPOINT_TX_FIFO12 0x00200720 +#define DATA_IN_ENDPOINT_TX_FIFO13 0x00200740 +#define DATA_IN_ENDPOINT_TX_FIFO14 0x00200760 +#define DATA_IN_ENDPOINT_TX_FIFO15 0x00200F00 + +/*DWC_OTG regsiter descriptor*/ +/*Device mode CSR MAP*/ +#define DEVICE_CSR_BASE 0x800 +/*Device mode CSR MAP*/ +#define DEVICE_INEP_BASE 0x900 +/*Device mode CSR MAP*/ +#define DEVICE_OUTEP_BASE 0xB00 + +/*** OTG LINK CORE REGISTERS ***/ +/* Core Global Registers */ +#define GOTGCTL 0x000 +#define GOTGINT 0x004 +#define GAHBCFG 0x008 +#define GAHBCFG_P_TXF_EMP_LVL (1 << 8) +#define GAHBCFG_NP_TXF_EMP_LVL (1 << 7) +#define GAHBCFG_DMA_EN (1 << 5) +#define GAHBCFG_GLBL_INTR_EN (1 << 0) +#define GAHBCFG_CTRL_MASK (GAHBCFG_P_TXF_EMP_LVL | \ + GAHBCFG_NP_TXF_EMP_LVL | \ + GAHBCFG_DMA_EN | \ + GAHBCFG_GLBL_INTR_EN) + +#define GUSBCFG 0x00C +#define GUSBCFG_USBTRDTIM_8BIT (0x9 << 10) +#define GUSBCFG_USBTRDTIM_16BIT (0x5 << 10) + +#define GRSTCTL 0x010 +#define GRSTCTL_AHBIDLE (1 << 31) +#define GRSTCTL_CSFTRST (1 << 0) + +#define GINTSTS 0x014 +#define GINTSTS_WKUPINT BIT31 +#define GINTSTS_SESSREGINT BIT30 +#define GINTSTS_DISCONNINT BIT29 +#define GINTSTS_CONIDSTSCHNG BIT28 +#define GINTSTS_LPMTRANRCVD BIT27 +#define GINTSTS_PTXFEMP BIT26 +#define GINTSTS_HCHINT BIT25 +#define GINTSTS_PRTINT BIT24 +#define GINTSTS_RESETDET BIT23 +#define GINTSTS_FET_SUSP BIT22 +#define GINTSTS_INCOMPL_IP BIT21 +#define GINTSTS_INCOMPL_SOIN BIT20 +#define GINTSTS_OEPINT BIT19 +#define GINTSTS_IEPINT BIT18 +#define GINTSTS_EPMIS BIT17 +#define GINTSTS_RESTOREDONE BIT16 +#define GINTSTS_EOPF BIT15 +#define GINTSTS_ISOUTDROP BIT14 +#define GINTSTS_ENUMDONE BIT13 +#define GINTSTS_USBRST BIT12 +#define GINTSTS_USBSUSP BIT11 +#define GINTSTS_ERLYSUSP BIT10 +#define GINTSTS_I2CINT BIT9 +#define GINTSTS_ULPI_CK_INT BIT8 +#define GINTSTS_GOUTNAKEFF BIT7 +#define GINTSTS_GINNAKEFF BIT6 +#define GINTSTS_NPTXFEMP BIT5 +#define GINTSTS_RXFLVL BIT4 +#define GINTSTS_SOF BIT3 +#define GINTSTS_OTGINT BIT2 +#define GINTSTS_MODEMIS BIT1 +#define GINTSTS_CURMODE_HOST BIT0 + +#define GINTMSK 0x018 +#define GRXSTSR 0x01C +#define GRXSTSP 0x020 +#define GRXFSIZ 0x024 +#define GNPTXFSIZ 0x028 +#define GNPTXSTS 0x02C + +#define GHWCFG1 0x044 +#define GHWCFG2 0x048 +#define GHWCFG3 0x04c +#define GHWCFG4 0x050 +#define GLPMCFG 0x054 + +#define GDFIFOCFG 0x05c + +#define HPTXFSIZ 0x100 +#define DIEPTXF(x) (0x100 + 4 * (x)) +#define DIEPTXF1 0x104 +#define DIEPTXF2 0x108 +#define DIEPTXF3 0x10C +#define DIEPTXF4 0x110 +#define DIEPTXF5 0x114 +#define DIEPTXF6 0x118 +#define DIEPTXF7 0x11C +#define DIEPTXF8 0x120 +#define DIEPTXF9 0x124 +#define DIEPTXF10 0x128 +#define DIEPTXF11 0x12C +#define DIEPTXF12 0x130 +#define DIEPTXF13 0x134 +#define DIEPTXF14 0x138 +#define DIEPTXF15 0x13C + +/*** HOST MODE REGISTERS ***/ +/* Host Global Registers */ +#define HCFG 0x400 +#define HFIR 0x404 +#define HFNUM 0x408 +#define HPTXSTS 0x410 +#define HAINT 0x414 +#define HAINTMSK 0x418 + +/* Host Port Control and Status Registers */ +#define HPRT 0x440 + +/* Host Channel-Specific Registers */ +#define HCCHAR(x) (0x500 + 0x20 * (x)) +#define HCSPLT(x) (0x504 + 0x20 * (x)) +#define HCINT(x) (0x508 + 0x20 * (x)) +#define HCINTMSK(x) (0x50C + 0x20 * (x)) +#define HCTSIZ(x) (0x510 + 0x20 * (x)) +#define HCDMA(x) (0x514 + 0x20 * (x)) +#define HCCHAR0 0x500 +#define HCSPLT0 0x504 +#define HCINT0 0x508 +#define HCINTMSK0 0x50C +#define HCTSIZ0 0x510 +#define HCDMA0 0x514 +#define HCCHAR1 0x520 +#define HCSPLT1 0x524 +#define HCINT1 0x528 +#define HCINTMSK1 0x52C +#define HCTSIZ1 0x530 +#define HCDMA1 0x534 +#define HCCHAR2 0x540 +#define HCSPLT2 0x544 +#define HCINT2 0x548 +#define HCINTMSK2 0x54C +#define HCTSIZ2 0x550 +#define HCDMA2 0x554 +#define HCCHAR3 0x560 +#define HCSPLT3 0x564 +#define HCINT3 0x568 +#define HCINTMSK3 0x56C +#define HCTSIZ3 0x570 +#define HCDMA3 0x574 +#define HCCHAR4 0x580 +#define HCSPLT4 0x584 +#define HCINT4 0x588 +#define HCINTMSK4 0x58C +#define HCTSIZ4 0x590 +#define HCDMA4 0x594 +#define HCCHAR5 0x5A0 +#define HCSPLT5 0x5A4 +#define HCINT5 0x5A8 +#define HCINTMSK5 0x5AC +#define HCTSIZ5 0x5B0 +#define HCDMA5 0x5B4 +#define HCCHAR6 0x5C0 +#define HCSPLT6 0x5C4 +#define HCINT6 0x5C8 +#define HCINTMSK6 0x5CC +#define HCTSIZ6 0x5D0 +#define HCDMA6 0x5D4 +#define HCCHAR7 0x5E0 +#define HCSPLT7 0x5E4 +#define HCINT7 0x5E8 +#define HCINTMSK7 0x5EC +#define HCTSIZ7 0x5F0 +#define HCDMA7 0x5F4 +#define HCCHAR8 0x600 +#define HCSPLT8 0x604 +#define HCINT8 0x608 +#define HCINTMSK8 0x60C +#define HCTSIZ8 0x610 +#define HCDMA8 0x614 +#define HCCHAR9 0x620 +#define HCSPLT9 0x624 +#define HCINT9 0x628 +#define HCINTMSK9 0x62C +#define HCTSIZ9 0x630 +#define HCDMA9 0x634 +#define HCCHAR10 0x640 +#define HCSPLT10 0x644 +#define HCINT10 0x648 +#define HCINTMSK10 0x64C +#define HCTSIZ10 0x650 +#define HCDMA10 0x654 +#define HCCHAR11 0x660 +#define HCSPLT11 0x664 +#define HCINT11 0x668 +#define HCINTMSK11 0x66C +#define HCTSIZ11 0x670 +#define HCDMA11 0x674 +#define HCCHAR12 0x680 +#define HCSPLT12 0x684 +#define HCINT12 0x688 +#define HCINTMSK12 0x68C +#define HCTSIZ12 0x690 +#define HCDMA12 0x694 +#define HCCHAR13 0x6A0 +#define HCSPLT13 0x6A4 +#define HCINT13 0x6A8 +#define HCINTMSK13 0x6AC +#define HCTSIZ13 0x6B0 +#define HCDMA13 0x6B4 +#define HCCHAR14 0x6C0 +#define HCSPLT14 0x6C4 +#define HCINT14 0x6C8 +#define HCINTMSK14 0x6CC +#define HCTSIZ14 0x6D0 +#define HCDMA14 0x6D4 +#define HCCHAR15 0x6E0 +#define HCSPLT15 0x6E4 +#define HCINT15 0x6E8 +#define HCINTMSK15 0x6EC +#define HCTSIZ15 0x6F0 +#define HCDMA15 0x6F4 + +/*** DEVICE MODE REGISTERS ***/ +/* Device Global Registers */ +#define DCFG 0x800 +#define DCFG_DESCDMA BIT23 +#define DCFG_EPMISCNT_MASK (0x1F << 18) +#define DCFG_EPMISCNT_SHIFT 18 +#define DCFG_DEVADDR_MASK (0x7F << 4) +#define DCFG_DEVADDR_SHIFT 4 +#define DCFG_DEVADDR(x) (((x) << DCFG_DEVADDR_SHIFT) & DCFG_DEVADDR_MASK) +#define DCFG_NZ_STS_OUT_HSHK BIT2 + +#define DCTL 0x804 +#define DCTL_PWRONPRGDONE BIT11 +#define DCTL_GNPINNAKSTS BIT2 +#define DCTL_SFTDISCON BIT1 + +#define DSTS 0x808 +#define DSTS_ENUMSPD_MASK (0x3 << 1) +#define DSTS_ENUMSPD_HIGH (0 << 1) +#define DSTS_ENUMSPD_FULL (1 << 1) + +#define DIEPMSK 0x810 +#define DOEPMSK 0x814 + +#define DXEPMSK_TIMEOUTMSK BIT3 +#define DXEPMSK_AHBERMSK BIT2 +#define DXEPMSK_XFERCOMPLMSK BIT0 + +#define DAINT 0x818 +#define DAINTMSK 0x81C + +#define DAINTMSK_OUTEPMSK_SHIFT 16 +#define DAINTMSK_INEPMSK_SHIFT 0 + +#define DTKNQR1 0x820 +#define DTKNQR2 0x824 +#define DVBUSDIS 0x828 +#define DVBUSPULSE 0x82C +#define DTHRCTL 0x830 + +/* Device Logical IN Endpoint-Specific Registers */ +#define DIEPCTL(x) (0x900 + 0x20 * (x)) +#define DIEPINT(x) (0x908 + 0x20 * (x)) +#define DIEPTSIZ(x) (0x910 + 0x20 * (x)) +#define DIEPDMA(x) (0x914 + 0x20 * (x)) +#define DTXFSTS(x) (0x918 + 0x20 * (x)) + +#define DIEPCTL0 0x900 +#define DIEPINT0 0x908 +#define DIEPTSIZ0 0x910 +#define DIEPDMA0 0x914 +#define DIEPCTL1 0x920 +#define DIEPINT1 0x928 +#define DIEPTSIZ1 0x930 +#define DIEPDMA1 0x934 +#define DIEPCTL2 0x940 +#define DIEPINT2 0x948 +#define DIEPTSIZ2 0x950 +#define DIEPDMA2 0x954 +#define DIEPCTL3 0x960 +#define DIEPINT3 0x968 +#define DIEPTSIZ3 0x970 +#define DIEPDMA3 0x974 +#define DIEPCTL4 0x980 +#define DIEPINT4 0x988 +#define DIEPTSIZ4 0x990 +#define DIEPDMA4 0x994 +#define DIEPCTL5 0x9A0 +#define DIEPINT5 0x9A8 +#define DIEPTSIZ5 0x9B0 +#define DIEPDMA5 0x9B4 +#define DIEPCTL6 0x9C0 +#define DIEPINT6 0x9C8 +#define DIEPTSIZ6 0x9D0 +#define DIEPDMA6 0x9D4 +#define DIEPCTL7 0x9E0 +#define DIEPINT7 0x9E8 +#define DIEPTSIZ7 0x9F0 +#define DIEPDMA7 0x9F4 +#define DIEPCTL8 0xA00 +#define DIEPINT8 0xA08 +#define DIEPTSIZ8 0xA10 +#define DIEPDMA8 0xA14 +#define DIEPCTL9 0xA20 +#define DIEPINT9 0xA28 +#define DIEPTSIZ9 0xA30 +#define DIEPDMA9 0xA34 +#define DIEPCTL10 0xA40 +#define DIEPINT10 0xA48 +#define DIEPTSIZ10 0xA50 +#define DIEPDMA10 0xA54 +#define DIEPCTL11 0xA60 +#define DIEPINT11 0xA68 +#define DIEPTSIZ11 0xA70 +#define DIEPDMA11 0xA74 +#define DIEPCTL12 0xA80 +#define DIEPINT12 0xA88 +#define DIEPTSIZ12 0xA90 +#define DIEPDMA12 0xA94 +#define DIEPCTL13 0xAA0 +#define DIEPINT13 0xAA8 +#define DIEPTSIZ13 0xAB0 +#define DIEPDMA13 0xAB4 +#define DIEPCTL14 0xAC0 +#define DIEPINT14 0xAC8 +#define DIEPTSIZ14 0xAD0 +#define DIEPDMA14 0xAD4 +#define DIEPCTL15 0xAE0 +#define DIEPINT15 0xAE8 +#define DIEPTSIZ15 0xAF0 +#define DIEPDMA15 0xAF4 + +/* Device Logical OUT Endpoint-Specific Registers */ +#define DOEPCTL(x) (0xB00 + 0x20 * (x)) +#define DOEPINT(x) (0xB08 + 0x20 * (x)) +#define DOEPTSIZ(x) (0xB10 + 0x20 * (x)) + +#define DXEPINT_EPDISBLD BIT1 +#define DXEPINT_XFERCOMPL BIT0 + +#define DXEPTSIZ_SUPCNT(x) (((x) & 0x3) << 29) +#define DXEPTSIZ_PKTCNT(x) (((x) & 0x3) << 19) +#define DXEPTSIZ_XFERSIZE(x) ((x) & 0x7F) + +#define DOEPDMA(x) (0xB14 + 0x20 * (x)) +#define DOEPCTL0 0xB00 +#define DOEPINT0 0xB08 +#define DOEPTSIZ0 0xB10 +#define DOEPDMA0 0xB14 +#define DOEPCTL1 0xB20 +#define DOEPINT1 0xB28 +#define DOEPTSIZ1 0xB30 +#define DOEPDMA1 0xB34 +#define DOEPCTL2 0xB40 +#define DOEPINT2 0xB48 +#define DOEPTSIZ2 0xB50 +#define DOEPDMA2 0xB54 +#define DOEPCTL3 0xB60 +#define DOEPINT3 0xB68 +#define DOEPTSIZ3 0xB70 +#define DOEPDMA3 0xB74 +#define DOEPCTL4 0xB80 +#define DOEPINT4 0xB88 +#define DOEPTSIZ4 0xB90 +#define DOEPDMA4 0xB94 +#define DOEPCTL5 0xBA0 +#define DOEPINT5 0xBA8 +#define DOEPTSIZ5 0xBB0 +#define DOEPDMA5 0xBB4 +#define DOEPCTL6 0xBC0 +#define DOEPINT6 0xBC8 +#define DOEPTSIZ6 0xBD0 +#define DOEPDMA6 0xBD4 +#define DOEPCTL7 0xBE0 +#define DOEPINT7 0xBE8 +#define DOEPTSIZ7 0xBF0 +#define DOEPDMA7 0xBF4 +#define DOEPCTL8 0xC00 +#define DOEPINT8 0xC08 +#define DOEPTSIZ8 0xC10 +#define DOEPDMA8 0xC14 +#define DOEPCTL9 0xC20 +#define DOEPINT9 0xC28 +#define DOEPTSIZ9 0xC30 +#define DOEPDMA9 0xC34 +#define DOEPCTL10 0xC40 +#define DOEPINT10 0xC48 +#define DOEPTSIZ10 0xC50 +#define DOEPDMA10 0xC54 +#define DOEPCTL11 0xC60 +#define DOEPINT11 0xC68 +#define DOEPTSIZ11 0xC70 +#define DOEPDMA11 0xC74 +#define DOEPCTL12 0xC80 +#define DOEPINT12 0xC88 +#define DOEPTSIZ12 0xC90 +#define DOEPDMA12 0xC94 +#define DOEPCTL13 0xCA0 +#define DOEPINT13 0xCA8 +#define DOEPTSIZ13 0xCB0 +#define DOEPDMA13 0xCB4 +#define DOEPCTL14 0xCC0 +#define DOEPINT14 0xCC8 +#define DOEPTSIZ14 0xCD0 +#define DOEPDMA14 0xCD4 +#define DOEPCTL15 0xCE0 +#define DOEPINT15 0xCE8 +#define DOEPTSIZ15 0xCF0 +#define DOEPDMA15 0xCF4 + +#define DXEPCTL_EPENA BIT31 +#define DXEPCTL_SNAK BIT27 +#define DXEPCTL_CNAK BIT26 +#define DXEPCTL_TXFNUM(x) (((x) & 0xF) << 22) +#define DXEPCTL_STALL BIT21 +#define DXEPCTL_EPTYPE_MASK (BIT19 | BIT18) +#define DXEPCTL_EPTYPE(x) (((x) & 0x3) << 18) +#define DXEPCTL_NAKSTS BIT17 +#define DXEPCTL_USBACTEP BIT15 +#define DXEPCTL_MPS_MASK 0x7FF + +#define DXEPTSIZN_PKTCNT_MASK (0x3FF << 19) +#define DXEPTSIZN_PKTCNT(x) (((x) & 0x3FF) << 19) +#define DXEPTSIZN_XFERSIZE_MASK 0x7FFFF +#define DXEPTSIZN_XFERSIZE(x) ((x) & 0x7FFFF) + +/* Power and Clock Gating Register */ +#define PCGCCTL 0xE00 + +#define EP0FIFO 0x1000 + +/** + * This union represents the bit fields in the DMA Descriptor + * status quadlet. Read the quadlet into the d32 member then + * set/clear the bits using the bit, b_iso_out and + * b_iso_in elements. + */ +typedef union { + /** raw register data */ + UINT32 d32; + /** quadlet bits */ + struct { + /** Received number of bytes */ + unsigned bytes:16; + /** NAK bit - only for OUT EPs */ + unsigned nak:1; + unsigned reserved17_22:6; + /** Multiple Transfer - only for OUT EPs */ + unsigned mtrf:1; + /** Setup Packet received - only for OUT EPs */ + unsigned sr:1; + /** Interrupt On Complete */ + unsigned ioc:1; + /** Short Packet */ + unsigned sp:1; + /** Last */ + unsigned l:1; + /** Receive Status */ + unsigned sts:2; + /** Buffer Status */ + unsigned bs:2; + } b; +} DevDmaDescStatus; + +/** + * DMA Descriptor structure + * + * DMA Descriptor structure contains two quadlets: + * Status quadlet and Data buffer pointer. + */ +typedef struct { + /** DMA Descriptor status quadlet */ + DevDmaDescStatus status; + /** DMA Descriptor data buffer pointer */ + UINT32 buf; +} DwUsbDevDmaDesc; + +#endif //ifndef __DW_USB_DXE_H__ diff --git a/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf new file mode 100644 index 0000000..989c6a4 --- /dev/null +++ b/Drivers/Usb/DwUsbDxe/DwUsbDxe.inf @@ -0,0 +1,52 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = DwUsbDxe + FILE_GUID = 72d78ea6-4dee-11e3-8100-f3842a48d0a0 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = DwUsbEntryPoint + +[Sources.common] + DwUsbDxe.c + +[LibraryClasses] + ArmLib + CacheMaintenanceLib + DebugLib + IoLib + MemoryAllocationLib + TimerLib + UncachedMemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gEfiDriverBindingProtocolGuid + gUsbDeviceProtocolGuid + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec + +[Pcd] + gDwUsbDxeTokenSpaceGuid.PcdDwUsbDxeBaseAddress + +[Depex] + TRUE diff --git a/Include/Protocol/DwUsb.h b/Include/Protocol/DwUsb.h new file mode 100644 index 0000000..040e126 --- /dev/null +++ b/Include/Protocol/DwUsb.h @@ -0,0 +1,81 @@ +/** @file + + Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __DW_USB_H__ +#define __DW_USB_H__ + +// +// Protocol GUID +// +#define DW_USB_PROTOCOL_GUID { 0x109fa264, 0x7811, 0x4862, { 0xa9, 0x73, 0x4a, 0xb2, 0xef, 0x2e, 0xe2, 0xff }} + +// +// Protocol interface structure +// +typedef struct _DW_USB_PROTOCOL DW_USB_PROTOCOL; + +#define USB_HOST_MODE 0 +#define USB_DEVICE_MODE 1 +#define USB_CABLE_NOT_ATTACHED 2 + +#define LANG_LENGTH 8 +#define MANU_FACTURER_STRING_LENGTH 32 +#define PRODUCT_STRING_LENGTH 32 +#define SERIAL_STRING_LENGTH 17 + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_LANG) ( + OUT CHAR16 *Lang, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_MANU_FACTURER) ( + OUT CHAR16 *ManuFacturer, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_PRODUCT) ( + OUT CHAR16 *Product, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_GET_SERIAL_NO) ( + OUT CHAR16 *SerialNo, + OUT UINT8 *Length + ); + +typedef +EFI_STATUS +(EFIAPI *DW_USB_PHY_INIT) ( + IN UINT8 Mode + ); + +struct _DW_USB_PROTOCOL { + DW_USB_GET_LANG GetLang; + DW_USB_GET_MANU_FACTURER GetManuFacturer; + DW_USB_GET_PRODUCT GetProduct; + DW_USB_GET_SERIAL_NO GetSerialNo; + DW_USB_PHY_INIT PhyInit; +}; + +extern EFI_GUID gDwUsbProtocolGuid; + +#endif From patchwork Wed Feb 15 14:54:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 94019 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp2064159qgi; Wed, 15 Feb 2017 06:55:58 -0800 (PST) X-Received: by 10.55.12.67 with SMTP id 64mr31482604qkm.171.1487170558504; Wed, 15 Feb 2017 06:55:58 -0800 (PST) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id f12si2993573qkf.134.2017.02.15.06.55.58; Wed, 15 Feb 2017 06:55:58 -0800 (PST) Received-SPF: pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=linaro-uefi-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 2855060859; Wed, 15 Feb 2017 14:55:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 9A3A36074F; Wed, 15 Feb 2017 14:55:36 +0000 (UTC) X-Original-To: linaro-uefi@lists.linaro.org Delivered-To: linaro-uefi@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 7100762D3B; Wed, 15 Feb 2017 14:55:29 +0000 (UTC) Received: from mail-pf0-f182.google.com (mail-pf0-f182.google.com [209.85.192.182]) by lists.linaro.org (Postfix) with ESMTPS id 9D89062D49 for ; Wed, 15 Feb 2017 14:55:15 +0000 (UTC) Received: by mail-pf0-f182.google.com with SMTP id 202so29090839pfx.2 for ; Wed, 15 Feb 2017 06:55:15 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=dSOOyceurzfK4sG+rUSjQT+aGWadjbYgnKBpP4KvLHE=; b=aXI04jf61SuI12wkYcdvQNdIzbqSp3zG4c6FX3xGvc27tsypv2WHEAaygCBtnlNz3/ 1ZcWbE/TKoDnJv8gYjxIg/aTtpMQ+ZJOE7eMF9rMHLlEOLkUp8zBN6W19K5sPTal9b97 o3drbFRr8vCnOL3Ss/6eEC5nUNEXRzNMpvuBsXNwwvdsuFWols6eEhHx11d6hbs2aoUF gO52oARsap7F+RrSPIc0dXig/fsQn+MX7sRwdw1KitB+NdhB4IqCG+owtajUCwFbIYaN nizMsI5Mawy1mARVxCukEF5Stq1jMkAaM6meEVKL8+dYtCHBO0ZMAyIH3ZCTxXqSOSCR oN+Q== X-Gm-Message-State: AMke39n9ehvD2D/yiGkPrVPr9BRgg2g5itUPs8WhH5krqWJg13nTJokOWu9ZgNUDtTlB4DHMZSQ= X-Received: by 10.84.225.20 with SMTP id t20mr44432297plj.154.1487170514726; Wed, 15 Feb 2017 06:55:14 -0800 (PST) Received: from localhost.localdomain ([45.56.159.211]) by smtp.gmail.com with ESMTPSA id s24sm8212782pgo.25.2017.02.15.06.55.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Feb 2017 06:55:14 -0800 (PST) From: Haojian Zhuang To: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org Date: Wed, 15 Feb 2017 22:54:57 +0800 Message-Id: <1487170499-22374-4-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> References: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> Subject: [Linaro-uefi] [PATCH v4 3/5] Platforms/Hisilicon/HiKey: support all GPIO controller X-BeenThere: linaro-uefi@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-uefi-bounces@lists.linaro.org Sender: "Linaro-uefi" Enable all PL061 GPIO controllers on HiKey platform. Without this, only one PL061 GPIO controller could be supported on HiKey platform. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang Reviewed-by: Leif Lindholm --- .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c | 96 ++++++++++++++++++++++ .../Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf | 38 +++++++++ 2 files changed, 134 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf diff --git a/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c new file mode 100644 index 0000000..4a2943c --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.c @@ -0,0 +1,96 @@ +/** @file +* +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include + +#include + +#include + +#include + +#define GPIO0_CTRL_PIN_BASE (0 * PL061_GPIO_PINS) +#define GPIO1_CTRL_PIN_BASE (1 * PL061_GPIO_PINS) +#define GPIO2_CTRL_PIN_BASE (2 * PL061_GPIO_PINS) +#define GPIO3_CTRL_PIN_BASE (3 * PL061_GPIO_PINS) +#define GPIO4_CTRL_PIN_BASE (4 * PL061_GPIO_PINS) +#define GPIO5_CTRL_PIN_BASE (5 * PL061_GPIO_PINS) +#define GPIO6_CTRL_PIN_BASE (6 * PL061_GPIO_PINS) +#define GPIO7_CTRL_PIN_BASE (7 * PL061_GPIO_PINS) +#define GPIO8_CTRL_PIN_BASE (8 * PL061_GPIO_PINS) +#define GPIO9_CTRL_PIN_BASE (9 * PL061_GPIO_PINS) +#define GPIO10_CTRL_PIN_BASE (10 * PL061_GPIO_PINS) +#define GPIO11_CTRL_PIN_BASE (11 * PL061_GPIO_PINS) +#define GPIO12_CTRL_PIN_BASE (12 * PL061_GPIO_PINS) +#define GPIO13_CTRL_PIN_BASE (13 * PL061_GPIO_PINS) +#define GPIO14_CTRL_PIN_BASE (14 * PL061_GPIO_PINS) +#define GPIO15_CTRL_PIN_BASE (15 * PL061_GPIO_PINS) +#define GPIO16_CTRL_PIN_BASE (16 * PL061_GPIO_PINS) +#define GPIO17_CTRL_PIN_BASE (17 * PL061_GPIO_PINS) +#define GPIO18_CTRL_PIN_BASE (18 * PL061_GPIO_PINS) +#define GPIO19_CTRL_PIN_BASE (19 * PL061_GPIO_PINS) + +#define GPIO_CTRL_NUMS 20 +#define GPIO_PIN_NUMS (GPIO_CTRL_NUMS * PL061_GPIO_PINS) + +GPIO_CONTROLLER gGpioDevice[]= { + { GPIO0_CTRL_BASE, GPIO0_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO1_CTRL_BASE, GPIO1_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO2_CTRL_BASE, GPIO2_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO3_CTRL_BASE, GPIO3_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO4_CTRL_BASE, GPIO4_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO5_CTRL_BASE, GPIO5_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO6_CTRL_BASE, GPIO6_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO7_CTRL_BASE, GPIO7_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO8_CTRL_BASE, GPIO8_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO9_CTRL_BASE, GPIO9_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO10_CTRL_BASE, GPIO10_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO11_CTRL_BASE, GPIO11_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO12_CTRL_BASE, GPIO12_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO13_CTRL_BASE, GPIO13_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO14_CTRL_BASE, GPIO14_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO15_CTRL_BASE, GPIO15_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO16_CTRL_BASE, GPIO16_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO17_CTRL_BASE, GPIO17_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO18_CTRL_BASE, GPIO18_CTRL_PIN_BASE, PL061_GPIO_PINS }, + { GPIO19_CTRL_BASE, GPIO19_CTRL_PIN_BASE, PL061_GPIO_PINS }, +}; + +PLATFORM_GPIO_CONTROLLER gPlatformGpioDevice = { + GPIO_PIN_NUMS, GPIO_CTRL_NUMS, gGpioDevice +}; + +EFI_STATUS +EFIAPI +HiKeyGpioEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + // Install the Embedded Platform GPIO Protocol onto a new handle + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gPlatformGpioProtocolGuid, &gPlatformGpioDevice, + NULL + ); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + } + + return Status; +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf new file mode 100644 index 0000000..d69c6f4 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyGpioDxe/HiKeyGpioDxe.inf @@ -0,0 +1,38 @@ +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyGpio + FILE_GUID = b51a851c-7bf7-463f-b261-cfb158b7f699 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyGpioEntryPoint + +[Sources.common] + HiKeyGpioDxe.c + +[Packages] + ArmPlatformPkg/ArmPlatformPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[LibraryClasses] + DebugLib + UefiDriverEntryPoint + +[Protocols] + gPlatformGpioProtocolGuid + +[Depex] + TRUE From patchwork Wed Feb 15 14:54:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 94021 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp2064901qgi; Wed, 15 Feb 2017 06:58:10 -0800 (PST) X-Received: by 10.107.201.12 with SMTP id z12mr31297894iof.220.1487170690150; Wed, 15 Feb 2017 06:58:10 -0800 (PST) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id b196si4269952ioa.42.2017.02.15.06.58.09; Wed, 15 Feb 2017 06:58:10 -0800 (PST) Received-SPF: pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=linaro-uefi-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 6734F6074F; Wed, 15 Feb 2017 14:58:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 819A260877; Wed, 15 Feb 2017 14:55:59 +0000 (UTC) X-Original-To: linaro-uefi@lists.linaro.org Delivered-To: linaro-uefi@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 2E45A6072A; Wed, 15 Feb 2017 14:55:52 +0000 (UTC) Received: from mail-pf0-f178.google.com (mail-pf0-f178.google.com [209.85.192.178]) by lists.linaro.org (Postfix) with ESMTPS id 30ED560C29 for ; Wed, 15 Feb 2017 14:55:18 +0000 (UTC) Received: by mail-pf0-f178.google.com with SMTP id e4so32125999pfg.1 for ; Wed, 15 Feb 2017 06:55:18 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=kGUKfzWfye1BcbqQXu3tEsOTz/934/oSI6vPbaxPT2U=; b=H4Q2JzZmIe46XZgys/YusUdM0RdoYYO0ClgdC7l0gvz2qaBstG18+boLyP13CeU52I 9+uei2vUTVNdZRJYx6frphWSkp1h9/A7NIAuevYDu2Ddn/TAR1ASr+1uuxEsix/aFO24 3lwLoZbngTNq1Irzl6EHwpX8hSLc4zg/91iKaWb9lJTh41CL4V8pWc3AM14ujg/WVCOx gF2cEY+Msn2lVzcBTuH9gQRTrxaYfa+iXkPFIsTSU/pvRpOAKnJZngv81V13/1GBytYf V8Rp+uaXPWMuNabiOHG1nOfAKRgVleYWa+p9pMBbLep34/iG3GprNWOPgHC1ivQsN66K yhqg== X-Gm-Message-State: AMke39ntQZtu6hQCoyeUyAWtwwMnxzuUQHXfIo2JDDTIW+T9QWsSJtK+XZ73b7XijGHqUIo+EvA= X-Received: by 10.84.211.106 with SMTP id b97mr29471799pli.16.1487170517360; Wed, 15 Feb 2017 06:55:17 -0800 (PST) Received: from localhost.localdomain ([45.56.159.211]) by smtp.gmail.com with ESMTPSA id s24sm8212782pgo.25.2017.02.15.06.55.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Feb 2017 06:55:16 -0800 (PST) From: Haojian Zhuang To: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org Date: Wed, 15 Feb 2017 22:54:58 +0800 Message-Id: <1487170499-22374-5-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> References: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> Subject: [Linaro-uefi] [PATCH v4 4/5] Platforms/Hisilicon/HiKey: support designware USB controller X-BeenThere: linaro-uefi@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-uefi-bounces@lists.linaro.org Sender: "Linaro-uefi" Support Designware USB device controller on HiKey platform. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang --- .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c | 265 +++++++++++++++++++++ .../Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf | 46 ++++ 2 files changed, 311 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf diff --git a/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c new file mode 100644 index 0000000..59ef57c --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.c @@ -0,0 +1,265 @@ +/** @file +* +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + + +#define USB_SEL_GPIO0_3 3 // GPIO 0_3 +#define USB_5V_HUB_EN 7 // GPIO 0_7 +#define USB_ID_DET_GPIO2_5 21 // GPIO 2_5 +#define USB_VBUS_DET_GPIO2_6 22 // GPIO 2_6 + +// Jumper on pin5-6 of J15 determines whether boot to fastboot +#define DETECT_J15_FASTBOOT 24 // GPIO 3_0 + +#define IOCG_GPIO0_BASE 0xF8001800 +#define IOCG_GPIO0_3_OFFSET 0x1C +#define IOCG_GPIO0_7_OFFSET 0x2C +#define IOCG_GPIO2_5_OFFSET 0x64 +#define IOCG_GPIO2_6_OFFSET 0x68 + +#define IOCG_PULLUP 1 +#define IOCG_PULLDOWN 2 + +#define USB_EYE_PATTERN 0x70533483 + +#define LANG_EN 0x409 + +STATIC EMBEDDED_GPIO *mGpio; + +STATIC +EFI_STATUS +HiKeyDetectUsbModeInit ( + IN VOID + ) +{ + EFI_STATUS Status; + + /* set pullup on both GPIO2_5 & GPIO2_6. It's required for inupt. */ + MmioWrite32 (IOCG_GPIO0_BASE + IOCG_GPIO2_5_OFFSET, IOCG_PULLUP); + MmioWrite32 (IOCG_GPIO0_BASE + IOCG_GPIO2_6_OFFSET, IOCG_PULLUP); + + Status = gBS->LocateProtocol (&gEmbeddedGpioProtocolGuid, NULL, (VOID **)&mGpio); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Can't locate gEmbeddedGpioProtocolGuid\n")); + return Status; + } + /* power on USB HUB */ + Status = mGpio->Set (mGpio, USB_5V_HUB_EN, GPIO_MODE_OUTPUT_0); + ASSERT_EFI_ERROR (Status); + /* start to detect USB device or host */ + Status = mGpio->Set (mGpio, USB_SEL_GPIO0_3, GPIO_MODE_OUTPUT_0); + ASSERT_EFI_ERROR (Status); + + Status = mGpio->Set (mGpio, USB_ID_DET_GPIO2_5, GPIO_MODE_INPUT); + ASSERT_EFI_ERROR (Status); + Status = mGpio->Set (mGpio, USB_VBUS_DET_GPIO2_6, GPIO_MODE_INPUT); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; +} + +UINTN +HiKeyGetUsbMode ( + IN VOID + ) +{ + EFI_STATUS Status; + UINTN GpioId, GpioVbus; + + Status = mGpio->Get (mGpio, USB_ID_DET_GPIO2_5, &GpioId); + ASSERT_EFI_ERROR (Status); + Status = mGpio->Get (mGpio, USB_VBUS_DET_GPIO2_6, &GpioVbus); + ASSERT_EFI_ERROR (Status); + + if ((GpioId == 1) && (GpioVbus == 0)) { + return USB_DEVICE_MODE; + } else if ((GpioId == 0) && (GpioVbus == 1)) { + return USB_CABLE_NOT_ATTACHED; + } + return USB_HOST_MODE; +} + +EFI_STATUS +HiKeyUsbPhyInit ( + IN UINT8 Mode + ) +{ + UINTN Value; + UINT32 Data; + EFI_STATUS Status; + + Status = HiKeyDetectUsbModeInit (); + if (EFI_ERROR (Status)) { + return Status; + } + + //setup clock + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CLKEN0, PERIPH_CLKEN0_USBOTG); + do { + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CLKSTAT0); + } while ((Value & PERIPH_CLKEN0_USBOTG) == 0); + + //setup phy + Data = RST0_USBOTG_BUS | RST0_POR_PICOPHY | + RST0_USBOTG | RST0_USBOTG_32K; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_RSTDIS0, Data); + do { + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_RSTSTAT0); + Value &= Data; + } while (Value); + + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4); + Value &= ~(CTRL4_PICO_SIDDQ | CTRL4_FPGA_EXT_PHY_SEL | + CTRL4_OTG_PHY_SEL); + Value |= CTRL4_PICO_VBUSVLDEXT | CTRL4_PICO_VBUSVLDEXTSEL; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL4, Value); + + if (HiKeyGetUsbMode () != Mode) { + return EFI_INVALID_PARAMETER; + } + //If Mode = 1, USB in Device Mode + //If Mode = 0, USB in Host Mode + if (Mode == USB_DEVICE_MODE) { + DEBUG ((DEBUG_INFO, "usb work as device mode.\n")); + + Value = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5); + Value &= ~CTRL5_PICOPHY_BC_MODE; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Value); + /* wait for stable */ + MicroSecondDelay (20000); + } else { + DEBUG ((DEBUG_INFO, "usb work as host mode.\n")); + + /*CTRL5*/ + Data = MmioRead32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5); + Data &= ~CTRL5_PICOPHY_BC_MODE; + Data |= CTRL5_USBOTG_RES_SEL | CTRL5_PICOPHY_ACAENB | + CTRL5_PICOPHY_VDATDETENB | CTRL5_PICOPHY_DCDENB; + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL5, Data); + /* wait for stable */ + MicroSecondDelay (20000); + /* Set the USB phy timing with tuned value that shows an eye pattern on oscillator. */ + MmioWrite32 (PERI_CTRL_BASE + SC_PERIPH_CTRL8, USB_EYE_PATTERN); + /* wait for eye pattern effective */ + MicroSecondDelay (5000); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetLang ( + OUT CHAR16 *Lang, + OUT UINT8 *Length + ) +{ + if ((Lang == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + Lang[0] = LANG_EN; + *Length = sizeof (CHAR16); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetManufacturer ( + OUT CHAR16 *Manufacturer, + OUT UINT8 *Length + ) +{ + CHAR16 DataUnicode[] = L"96Boards"; + + if ((Manufacturer == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + StrCpy (Manufacturer, DataUnicode); + /* include '\0' for string */ + *Length = (StrLen (DataUnicode) + 1) * sizeof (CHAR16); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetProduct ( + OUT CHAR16 *Product, + OUT UINT8 *Length + ) +{ + CHAR16 DataUnicode[] = L"HiKey"; + + if ((Product == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + StrCpy (Product, DataUnicode); + /* include '\0' for string */ + *Length = (StrLen (DataUnicode) + 1) * sizeof (CHAR16); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiKeyUsbGetSerialNo ( + OUT CHAR16 *SerialNo, + OUT UINT8 *Length + ) +{ + CHAR16 DataUnicode[] = L"0123456789abcdef"; + + if ((SerialNo == NULL) || (Length == NULL)) { + return EFI_INVALID_PARAMETER; + } + StrCpy (SerialNo, DataUnicode); + /* include '\0' for string */ + *Length = (StrLen (DataUnicode) + 1) * sizeof (CHAR16); + return EFI_SUCCESS; +} + +DW_USB_PROTOCOL mDwUsbDevice = { + HiKeyUsbGetLang, + HiKeyUsbGetManufacturer, + HiKeyUsbGetProduct, + HiKeyUsbGetSerialNo, + HiKeyUsbPhyInit +}; + +EFI_STATUS +EFIAPI +HiKeyUsbEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gDwUsbProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDwUsbDevice + ); + return Status; +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf new file mode 100644 index 0000000..57d639a --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyUsbDxe/HiKeyUsbDxe.inf @@ -0,0 +1,46 @@ +#/** @file +# +# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyUsbDxe + FILE_GUID = c5c7089e-9b00-448c-8b23-a552688e2833 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyUsbEntryPoint + +[Sources.common] + HiKeyUsbDxe.c + +[LibraryClasses] + DebugLib + IoLib + TimerLib + UefiBootServicesTableLib + UefiDriverEntryPoint + +[Protocols] + gDwUsbProtocolGuid + gEfiDriverBindingProtocolGuid + gEmbeddedGpioProtocolGuid + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + OpenPlatformPkg/Drivers/Usb/DwUsbDxe/DwUsbDxe.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[Depex] + TRUE From patchwork Wed Feb 15 14:54:59 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Haojian Zhuang X-Patchwork-Id: 94022 Delivered-To: patch@linaro.org Received: by 10.140.20.99 with SMTP id 90csp2065063qgi; Wed, 15 Feb 2017 06:58:39 -0800 (PST) X-Received: by 10.200.36.81 with SMTP id d17mr30708429qtd.99.1487170719797; Wed, 15 Feb 2017 06:58:39 -0800 (PST) Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id p33si3007456qtb.68.2017.02.15.06.58.39; Wed, 15 Feb 2017 06:58:39 -0800 (PST) Received-SPF: pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linaro-uefi-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=linaro-uefi-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 49484607D9; Wed, 15 Feb 2017 14:58:39 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id BA5926352A; Wed, 15 Feb 2017 14:56:06 +0000 (UTC) X-Original-To: linaro-uefi@lists.linaro.org Delivered-To: linaro-uefi@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id B68E460877; Wed, 15 Feb 2017 14:55:54 +0000 (UTC) Received: from mail-pg0-f44.google.com (mail-pg0-f44.google.com [74.125.83.44]) by lists.linaro.org (Postfix) with ESMTPS id 3F5ED62CB6 for ; Wed, 15 Feb 2017 14:55:21 +0000 (UTC) Received: by mail-pg0-f44.google.com with SMTP id 204so37661078pge.0 for ; Wed, 15 Feb 2017 06:55:21 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=K7jadIWj49Jz3CFyj50SlxE3g7dH6EpNXJ894aXTDZo=; b=cO/BANjJVzqT4Z8UjdKGKP4r76FNkCWHOl/MIgo4B+blpY8dFs/MOiAQWpFS5yxGbp /JssoOud2hAmO2T9uhdjvWRnwYJRxmdoTjbulpoJyE/2JD+uRDiwrENd0cwUxLRyCE81 7G/uBn3MiwcevdUhV34ap2Vp6qK7HS+pYo1lFfVAUoZNVUVQSDHqn+iuJ6ZNJ2JpuiRF 1M4PUp5/MuWA5MELeG6G+4P+gXgMxSH0g63MoxW/NhOYELw0wpJRpSUE1vyIgQWMtk8y tpxPjRAjv33fpw2OzbkpZmWkl73DqwONsmgxt0O23NZL2i71yQjIQ5iLUAO5NG4VG5eL IvlA== X-Gm-Message-State: AMke39mtAwN+3XxiEGnAd/migBRs9lejJWckiwQronw5VxcJMn7o3K3i3NIqkBzUJDImzBfLzeI= X-Received: by 10.84.218.11 with SMTP id q11mr37653654pli.141.1487170520017; Wed, 15 Feb 2017 06:55:20 -0800 (PST) Received: from localhost.localdomain ([45.56.159.211]) by smtp.gmail.com with ESMTPSA id s24sm8212782pgo.25.2017.02.15.06.55.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 15 Feb 2017 06:55:19 -0800 (PST) From: Haojian Zhuang To: ard.biesheuvel@linaro.org, leif.lindholm@linaro.org, linaro-uefi@lists.linaro.org Date: Wed, 15 Feb 2017 22:54:59 +0800 Message-Id: <1487170499-22374-6-git-send-email-haojian.zhuang@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> References: <1487170499-22374-1-git-send-email-haojian.zhuang@linaro.org> Subject: [Linaro-uefi] [PATCH v4 5/5] Platforms/Hisilicon/HiKey: add fastboot driver X-BeenThere: linaro-uefi@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: linaro-uefi-bounces@lists.linaro.org Sender: "Linaro-uefi" Support HiKey Fastboot driver for Fastboot App. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Haojian Zhuang --- Platforms/Hisilicon/HiKey/HiKey.dec | 1 + .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c | 672 +++++++++++++++++++++ .../HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf | 61 ++ .../Hisilicon/HiKey/Include/Guid/HiKeyVariable.h | 24 + 4 files changed, 758 insertions(+) create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c create mode 100644 Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf create mode 100644 Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h diff --git a/Platforms/Hisilicon/HiKey/HiKey.dec b/Platforms/Hisilicon/HiKey/HiKey.dec index 537138e..17c6484 100644 --- a/Platforms/Hisilicon/HiKey/HiKey.dec +++ b/Platforms/Hisilicon/HiKey/HiKey.dec @@ -30,6 +30,7 @@ [Guids.common] gHiKeyTokenSpaceGuid = { 0x91148425, 0xcdd2, 0x4830, { 0x8b, 0xd0, 0xc6, 0x1c, 0x6d, 0xea, 0x36, 0x21 } } + gHiKeyVariableGuid = { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } [PcdsFixedAtBuild.common] gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath|L""|VOID*|0x00000001 diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c new file mode 100644 index 0000000..2597f7a --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.c @@ -0,0 +1,672 @@ +/** @file + + Copyright (c) 2014, ARM Ltd. All rights reserved.
+ Copyright (c) 2015-2017, Linaro. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +/* + Implementation of the Android Fastboot Platform protocol, to be used by the + Fastboot UEFI application, for Hisilicon HiKey platform. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define FLASH_DEVICE_PATH_SIZE(DevPath) ( GetDevicePathSize (DevPath) - \ + sizeof (EFI_DEVICE_PATH_PROTOCOL)) + +#define PARTITION_NAME_MAX_LENGTH 72/2 + +#define IS_ALPHA(Char) (((Char) <= L'z' && (Char) >= L'a') || \ + ((Char) <= L'Z' && (Char) >= L'Z')) +#define IS_HEXCHAR(Char) (((Char) <= L'9' && (Char) >= L'0') || \ + IS_ALPHA(Char)) + +#define SERIAL_NUMBER_LENGTH 16 +#define BOOT_DEVICE_LENGTH 16 + +#define HIKEY_ERASE_SIZE (16 * 1024 * 1024) +#define HIKEY_ERASE_BLOCKS (HIKEY_ERASE_SIZE / EFI_PAGE_SIZE) +#define PARTITION_TYPE_STRING "partition-type" +#define PARTITION_SIZE_STRING "partition-size" +// length of a 12-byte hex string +#define PARTITION_SIZE_LENGTH 12 +#define PARTITION_NAME_LENGTH 36 // CHAR16 + +/* + * struct entry_head { + * unsigned char magic[8]; // "ENTRYHDR" + * unsigned char name[8]; // "primary"/"second" + * unsigned int start_lba; + * unsigned int count_lba; + * unsigned int flag; + * } + * + * ptable: + * ------------------------------------------------------ + * | head (primary) | content | head (second) | content | + * ------------------------------------------------------ + */ + +#define HIKEY_PTABLE_HEAD_MAGIC_LEN 8 +#define HIKEY_PTABLE_HEAD_NAME_LEN 8 +#define HIKEY_PTABLE_HEAD_SIZE 28 +#define HIKEY_PTABLE_CONTENT_OFFSET 512 + + +typedef struct _FASTBOOT_PARTITION_LIST { + LIST_ENTRY Link; + CHAR16 PartitionName[PARTITION_NAME_MAX_LENGTH]; + EFI_HANDLE PartitionHandle; + EFI_LBA Lba; +} FASTBOOT_PARTITION_LIST; + +STATIC LIST_ENTRY mPartitionListHead; + +/* + Helper to free the partition list +*/ +STATIC +VOID +FreePartitionList ( + VOID + ) +{ + FASTBOOT_PARTITION_LIST *Entry; + FASTBOOT_PARTITION_LIST *NextEntry; + + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&mPartitionListHead); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + NextEntry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &Entry->Link); + + RemoveEntryList (&Entry->Link); + FreePool (Entry); + + Entry = NextEntry; + } +} +/* + Read the PartitionName fields from the GPT partition entries, putting them + into an allocated array that should later be freed. +*/ +STATIC +EFI_STATUS +ReadPartitionEntries ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + OUT EFI_PARTITION_ENTRY **PartitionEntries + ) +{ + UINTN EntrySize; + UINTN NumEntries; + UINTN BufferSize; + UINT32 MediaId; + EFI_PARTITION_TABLE_HEADER *GptHeader; + EFI_STATUS Status; + + MediaId = BlockIo->Media->MediaId; + + // + // Read size of Partition entry and number of entries from GPT header + // + + GptHeader = AllocatePool (BlockIo->Media->BlockSize); + if (GptHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 1, BlockIo->Media->BlockSize, GptHeader); + if (EFI_ERROR (Status)) { + return Status; + } + + // Check there is a GPT on the media + if (GptHeader->Header.Signature != EFI_PTAB_HEADER_ID || + GptHeader->MyLBA != 1) { + DEBUG ((DEBUG_ERROR, + "Fastboot platform: No GPT on flash. " + "Fastboot on HiKey does not support MBR.\n" + )); + return EFI_DEVICE_ERROR; + } + + EntrySize = GptHeader->SizeOfPartitionEntry; + NumEntries = GptHeader->NumberOfPartitionEntries; + + FreePool (GptHeader); + + ASSERT (EntrySize != 0); + ASSERT (NumEntries != 0); + + BufferSize = ALIGN_VALUE (EntrySize * NumEntries, BlockIo->Media->BlockSize); + *PartitionEntries = AllocatePool (BufferSize); + if (PartitionEntries == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BlockIo->ReadBlocks (BlockIo, MediaId, 2, BufferSize, (VOID *) *PartitionEntries); + if (EFI_ERROR (Status)) { + FreePool (PartitionEntries); + return Status; + } + + return Status; +} + + +STATIC +EFI_STATUS +CreateGptPartitionEntry ( + IN EFI_HANDLE *AllHandles, + IN UINTN LoopIndex, + IN HARDDRIVE_DEVICE_PATH *PartitionNode, + IN EFI_PARTITION_ENTRY *PartitionEntries + ) +{ + FASTBOOT_PARTITION_LIST *Entry; + + // Create entry + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); + if (Entry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Copy handle and partition name + Entry->PartitionHandle = AllHandles[LoopIndex]; + StrnCpy ( + Entry->PartitionName, + PartitionEntries[PartitionNode->PartitionNumber - 1].PartitionName, // Partition numbers start from 1. + PARTITION_NAME_MAX_LENGTH + ); + Entry->Lba = PartitionEntries[PartitionNode->PartitionNumber - 1].StartingLBA; + InsertTailList (&mPartitionListHead, &Entry->Link); + + // Print a debug message if the partition label is empty or looks like + // garbage. + if (!IS_ALPHA (Entry->PartitionName[0])) { + DEBUG ((DEBUG_WARN, + "Warning: Partition %d doesn't seem to have a GPT partition label. " + "You won't be able to flash it with Fastboot.\n", + PartitionNode->PartitionNumber + )); + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +CreatePartitionEntry ( + IN EFI_HANDLE *AllHandles, + IN UINTN LoopIndex, + IN EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_PARTITION_ENTRY *PartitionEntries + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NextNode; + FASTBOOT_PARTITION_LIST *Entry; + HARDDRIVE_DEVICE_PATH *PartitionNode; + + // Fill out if it isn't a sub-device of the flash device + if (CompareMem (DevicePath, FlashDevicePath, FLASH_DEVICE_PATH_SIZE (FlashDevicePath))) { + return EFI_SUCCESS; + } + // Device path starts with path of flash device. Check it isn't the flash + // device itself. + NextNode = NextDevicePathNode (DevicePath); + if (IsDevicePathEndType (NextNode)) { + // Create entry + Entry = AllocatePool (sizeof (FASTBOOT_PARTITION_LIST)); + if (Entry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // Copy handle and partition name + Entry->PartitionHandle = AllHandles[LoopIndex]; + StrCpy (Entry->PartitionName, L"ptable"); + InsertTailList (&mPartitionListHead, &Entry->Link); + return EFI_SUCCESS; + } + + // Assert that this device path node represents a partition. + ASSERT (NextNode->Type == MEDIA_DEVICE_PATH && + NextNode->SubType == MEDIA_HARDDRIVE_DP); + + PartitionNode = (HARDDRIVE_DEVICE_PATH *) NextNode; + + // Assert that the partition type is GPT. ReadPartitionEntries checks for + // presence of a GPT, so we should never find MBR partitions. + // ("MBRType" is a misnomer - this field is actually called "Partition + // Format") + ASSERT (PartitionNode->MBRType == MBR_TYPE_EFI_PARTITION_TABLE_HEADER); + + // The firmware may install a handle for "partition 0", representing the + // whole device. Ignore it. + if (PartitionNode->PartitionNumber == 0) { + return EFI_SUCCESS; + } + return CreateGptPartitionEntry (AllHandles, LoopIndex, PartitionNode, PartitionEntries); +} + +/* + Initialise: Open the Android NVM device and find the partitions on it. Save them in + a list along with the "PartitionName" fields for their GPT entries. + We will use these partition names as the key in + HiKeyFastbootPlatformFlashPartition. +*/ +STATIC +EFI_STATUS +HiKeyFastbootPlatformInit ( + VOID + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FlashDevicePathDup; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN NumHandles; + EFI_HANDLE *AllHandles; + UINTN LoopIndex; + EFI_HANDLE FlashHandle; + EFI_BLOCK_IO_PROTOCOL *FlashBlockIo; + EFI_PARTITION_ENTRY *PartitionEntries; + + InitializeListHead (&mPartitionListHead); + + // + // Get EFI_HANDLES for all the partitions on the block devices pointed to by + // PcdFastbootFlashDevicePath, also saving their GPT partition labels. + // There's no way to find all of a device's children, so we get every handle + // in the system supporting EFI_BLOCK_IO_PROTOCOL and then filter out ones + // that don't represent partitions on the flash device. + // + + FlashDevicePath = ConvertTextToDevicePath ((CHAR16*)FixedPcdGetPtr (PcdAndroidFastbootNvmDevicePath)); + + // + // Open the Disk IO protocol on the flash device - this will be used to read + // partition names out of the GPT entries + // + // Create another device path pointer because LocateDevicePath will modify it. + FlashDevicePathDup = FlashDevicePath; + Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &FlashDevicePathDup, &FlashHandle); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Warning: Couldn't locate Android NVM device (status: %r)\n", Status)); + // Failing to locate partitions should not prevent to do other Android FastBoot actions + return EFI_SUCCESS; + } + + Status = gBS->OpenProtocol ( + FlashHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &FlashBlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: Couldn't open Android NVM device (status: %r)\n", Status)); + return EFI_DEVICE_ERROR; + } + + // Read the GPT partition entry array into memory so we can get the partition names + Status = ReadPartitionEntries (FlashBlockIo, &PartitionEntries); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Warning: Failed to read partitions from Android NVM device (status: %r)\n", Status)); + // Failing to locate partitions should not prevent to do other Android FastBoot actions + return EFI_SUCCESS; + } + + // Get every Block IO protocol instance installed in the system + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NumHandles, + &AllHandles + ); + ASSERT_EFI_ERROR (Status); + + // Filter out handles that aren't children of the flash device + for (LoopIndex = 0; LoopIndex < NumHandles; LoopIndex++) { + // Get the device path for the handle + Status = gBS->OpenProtocol ( + AllHandles[LoopIndex], + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + + Status = CreatePartitionEntry ( + AllHandles, + LoopIndex, + FlashDevicePath, + DevicePath, + PartitionEntries + ); + if (EFI_ERROR (Status)) { + FreePartitionList (); + goto Exit; + } + } + +Exit: + FreePool (PartitionEntries); + FreePool (FlashDevicePath); + FreePool (AllHandles); + return Status; + +} + +STATIC +VOID +HiKeyFastbootPlatformUnInit ( + VOID + ) +{ + FreePartitionList (); +} + +STATIC +VOID * +WritePartition ( + IN VOID *Image, + IN UINTN Size, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN CHAR8 *Name + ) +{ + UINT32 EntrySize, EntryOffset; + EFI_STATUS Status; + VOID *Buffer; + + Buffer = Image; + // not a string with terminated '\0' + if (AsciiStrnCmp (Buffer, "ENTRYHDR", HIKEY_PTABLE_HEAD_MAGIC_LEN) != 0) { + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); + return NULL; + } + Buffer += HIKEY_PTABLE_HEAD_MAGIC_LEN; + // not a string with terminated '\0' + if (AsciiStrnCmp (Buffer, Name, HIKEY_PTABLE_HEAD_NAME_LEN) != 0) { + DEBUG ((DEBUG_ERROR, "unknown ptable image\n")); + return NULL; + } + Buffer += HIKEY_PTABLE_HEAD_NAME_LEN; + EntryOffset = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + Buffer += sizeof (UINT32); + EntrySize = *(UINT32 *)Buffer * BlockIo->Media->BlockSize; + if ((EntrySize + HIKEY_PTABLE_CONTENT_OFFSET) > Size) { + DEBUG ((DEBUG_ERROR, "Entry size doesn't match\n")); + return NULL; + } + Buffer = Image + HIKEY_PTABLE_CONTENT_OFFSET; + Status = DiskIo->WriteDisk (DiskIo, BlockIo->Media->MediaId, EntryOffset, EntrySize, Buffer); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Can't flush partition table\n")); + return NULL; + } + Buffer += EntrySize; + return Buffer; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformFlashPartition ( + IN CHAR8 *PartitionName, + IN UINTN Size, + IN VOID *Image + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + UINT32 MediaId; + UINTN PartitionSize; + FASTBOOT_PARTITION_LIST *Entry; + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; + BOOLEAN PartitionFound; + VOID *Buffer; + + + AsciiStrToUnicodeStr (PartitionName, PartitionNameUnicode); + + PartitionFound = FALSE; + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + // Search the partition list for the partition named by PartitionName + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { + PartitionFound = TRUE; + break; + } + + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); + } + if (!PartitionFound) { + return EFI_NOT_FOUND; + } + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); + return EFI_NOT_FOUND; + } + + // Check image will fit on device + // LastBlock counts from 0 + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; + if (PartitionSize < Size) { + DEBUG ((DEBUG_ERROR, "Partition not big enough.\n")); + DEBUG ((DEBUG_ERROR, "Partition Size:\t%ld\nImage Size:\t%ld\n", PartitionSize, Size)); + + return EFI_VOLUME_FULL; + } + + MediaId = BlockIo->Media->MediaId; + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT_EFI_ERROR (Status); + + if (AsciiStrCmp (PartitionName, "ptable") == 0) { + Buffer = WritePartition (Image, Size, DiskIo, BlockIo, "primary"); + if (Buffer == NULL) { + return EFI_DEVICE_ERROR; + } + if (Size >= (2 * PartitionSize)) { + Buffer = WritePartition (Buffer, Size, DiskIo, BlockIo, "second"); + if (Buffer == NULL) { + return EFI_DEVICE_ERROR; + } + } + } else { + Status = DiskIo->WriteDisk (DiskIo, MediaId, 0, Size, Image); + } + + BlockIo->FlushBlocks(BlockIo); + // wait DMA finished + MicroSecondDelay (50000); + + return Status; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformErasePartition ( + IN CHAR8 *PartitionName + ) +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformGetVar ( + IN CHAR8 *Name, + OUT CHAR8 *Value + ) +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + UINT64 PartitionSize; + FASTBOOT_PARTITION_LIST *Entry; + CHAR16 PartitionNameUnicode[PARTITION_NAME_LENGTH]; + BOOLEAN PartitionFound; + CHAR16 DataUnicode[SERIAL_NUMBER_LENGTH + 1]; // terminated '\0' + UINTN VariableSize; + CHAR8 PartTypeStr[] = "partition-type"; + CHAR8 PartSizeStr[] = "partition-size"; + + if (!AsciiStrCmp (Name, "max-download-size")) { + AsciiStrCpy (Value, FixedPcdGetPtr (PcdArmFastbootFlashLimit)); + } else if (!AsciiStrCmp (Name, "product")) { + AsciiStrCpy (Value, FixedPcdGetPtr (PcdFirmwareVendor)); + } else if (!AsciiStrCmp (Name, "serialno")) { + VariableSize = (SERIAL_NUMBER_LENGTH + 1) * sizeof (CHAR16); + Status = gRT->GetVariable ( + (CHAR16 *)L"SerialNo", + &gHiKeyVariableGuid, + NULL, + &VariableSize, + &DataUnicode + ); + if (EFI_ERROR (Status)) { + *Value = '\0'; + return EFI_NOT_FOUND; + } + DataUnicode[SERIAL_NUMBER_LENGTH * sizeof(CHAR16)] = '\0'; + UnicodeStrToAsciiStr (DataUnicode, Value); + } else if (!AsciiStrnCmp (Name, PartSizeStr, AsciiStrLen (PartSizeStr))) { + // skip ':', then copy + AsciiStrToUnicodeStr ((Name + AsciiStrLen (PartSizeStr) + 1), PartitionNameUnicode); + PartitionFound = FALSE; + Entry = (FASTBOOT_PARTITION_LIST *) GetFirstNode (&(mPartitionListHead)); + while (!IsNull (&mPartitionListHead, &Entry->Link)) { + // Search the partition list for the partition named by PartitionName + if (StrCmp (Entry->PartitionName, PartitionNameUnicode) == 0) { + PartitionFound = TRUE; + break; + } + + Entry = (FASTBOOT_PARTITION_LIST *) GetNextNode (&mPartitionListHead, &(Entry)->Link); + } + if (!PartitionFound) { + *Value = '\0'; + return EFI_NOT_FOUND; + } + + Status = gBS->OpenProtocol ( + Entry->PartitionHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fastboot platform: couldn't open Block IO for flash: %r\n", Status)); + *Value = '\0'; + return EFI_NOT_FOUND; + } + + // LastBlock counts from 0 + PartitionSize = (BlockIo->Media->LastBlock + 1) * BlockIo->Media->BlockSize; + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-size:%a 0x%llx\n", Name, PartitionSize)); + AsciiSPrint (Value, PARTITION_SIZE_LENGTH, "0x%llx", PartitionSize); + } else if ( !AsciiStrnCmp (Name, PartTypeStr, AsciiStrLen (PartTypeStr))) { + DEBUG ((DEBUG_INFO, "Fastboot platform: check for partition-type:%a\n", Name + AsciiStrLen (PartTypeStr))); + // skip ':' + if (!AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "system") || + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "userdata") || + !AsciiStrCmp ((Name + AsciiStrLen (PartTypeStr) + 1) , "cache")) { + AsciiStrCpy (Value, "ext4"); + } else { + AsciiStrCpy (Value, "raw"); + } + } else { + *Value = '\0'; + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +HiKeyFastbootPlatformOemCommand ( + IN CHAR8 *Command + ) +{ + if (AsciiStrCmp (Command, "Demonstrate") == 0) { + DEBUG ((DEBUG_ERROR, "ARM OEM Fastboot command 'Demonstrate' received.\n")); + return EFI_SUCCESS; + } else { + DEBUG ((DEBUG_ERROR, + "HiKey: Unrecognised Fastboot OEM command: %s\n", + Command + )); + return EFI_NOT_FOUND; + } +} + +FASTBOOT_PLATFORM_PROTOCOL mPlatformProtocol = { + HiKeyFastbootPlatformInit, + HiKeyFastbootPlatformUnInit, + HiKeyFastbootPlatformFlashPartition, + HiKeyFastbootPlatformErasePartition, + HiKeyFastbootPlatformGetVar, + HiKeyFastbootPlatformOemCommand +}; + +EFI_STATUS +EFIAPI +HiKeyFastbootPlatformEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return gBS->InstallProtocolInterface ( + &ImageHandle, + &gAndroidFastbootPlatformProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPlatformProtocol + ); +} diff --git a/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf new file mode 100644 index 0000000..353c6c3 --- /dev/null +++ b/Platforms/Hisilicon/HiKey/HiKeyFastbootDxe/HiKeyFastbootDxe.inf @@ -0,0 +1,61 @@ +#/** @file +# +# Copyright (c) 2014, ARM Ltd. All rights reserved.
+# Copyright (c) 2015-2017, Linaro. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010019 + BASE_NAME = HiKeyFastbootDxe + FILE_GUID = 8e335c38-c4e1-494e-8011-37a858d9763d + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = HiKeyFastbootPlatformEntryPoint + +[Sources.common] + HiKeyFastbootDxe.c + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + PcdLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + TimerLib + +[Protocols] + gAndroidFastbootPlatformProtocolGuid + gEfiBlockIoProtocolGuid + gEfiDiskIoProtocolGuid + gEfiSimpleTextOutProtocolGuid + gEfiEraseBlockProtocolGuid + +[Packages] + EmbeddedPkg/EmbeddedPkg.dec + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVExpressPkg/ArmVExpressPkg.dec + ArmPkg/ArmPkg.dec + OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dec + +[Guids] + gHiKeyVariableGuid + +[Pcd] + gArmPlatformTokenSpaceGuid.PcdFirmwareVendor + gHiKeyTokenSpaceGuid.PcdAndroidFastbootNvmDevicePath + gHiKeyTokenSpaceGuid.PcdArmFastbootFlashLimit diff --git a/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h new file mode 100644 index 0000000..56d5a0e --- /dev/null +++ b/Platforms/Hisilicon/HiKey/Include/Guid/HiKeyVariable.h @@ -0,0 +1,24 @@ +/** @file +* +* Copyright (c) 2013-2014, ARM Limited. All rights reserved. +* Copyright (c) 2015-2017, Linaro. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef __HIKEY_VARIABLE_H__ +#define __HIKEY_VARIABLE_H__ + +#define HIKEY_VARIABLE_GUID \ + { 0x66b8d063, 0x1daa, 0x4c60, { 0xb9, 0xf2, 0x55, 0x0d, 0x7e, 0xe1, 0x2f, 0x38 } } + +extern EFI_GUID gHiKeyVariableGuid; + +#endif /* __HIKEY_VARIABLE_H__ */