aml usb wip
Change-Id: Ide2fdcfa7572e1b3dd55125f13b69fe9e98829d6
diff --git a/system/dev/board/aml-s905d2/aml-usb.c b/system/dev/board/aml-s905d2/aml-usb.c
index c6b1d24..82d4722 100644
--- a/system/dev/board/aml-s905d2/aml-usb.c
+++ b/system/dev/board/aml-s905d2/aml-usb.c
@@ -6,24 +6,22 @@
#include <ddk/protocol/platform-defs.h>
#include <hw/reg.h>
-#include <soc/aml-common/aml-usb-phy.h>
+#include <soc/aml-common/aml-usb-phy-v2.h>
+#include <soc/aml-s905d2/s905d2-gpio.h>
+#include <soc/aml-s905d2/s905d2-hw.h>
#include "aml.h"
-#define BIT_MASK(start, count) (((1 << (count)) - 1) << (start))
-#define SET_BITS(dest, start, count, value) \
- ((dest & ~BIT_MASK(start, count)) | (((value) << (start)) & BIT_MASK(start, count)))
-
static const pbus_mmio_t xhci_mmios[] = {
{
- .base = 0xc9000000,
- .length = 0x100000,
+ .base = S905D2_USB0_BASE,
+ .length = S905D2_USB0_LENGTH,
},
};
static const pbus_irq_t xhci_irqs[] = {
{
- .irq = 62,
+ .irq = S905D2_USBH_IRQ,
.mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
},
};
@@ -50,15 +48,22 @@
zx_status_t aml_usb_init(aml_bus_t* bus) {
zx_status_t status;
-
+ io_buffer_t reset_buf;
+ io_buffer_t usbctrl_buf;
zx_handle_t bti;
+
+ // FIXME - move to board hardware header
+ gpio_config(&bus->gpio, S905D2_GPIOH(6), GPIO_DIR_OUT);
+ gpio_write(&bus->gpio, S905D2_GPIOH(6), 1);
+
status = iommu_get_bti(&bus->iommu, 0, BTI_BOARD, &bti);
if (status != ZX_OK) {
- zxlogf(ERROR, "aml_bus_bind: iommu_get_bti failed: %d\n", status);
+ zxlogf(ERROR, "aml_usb_init: iommu_get_bti failed: %d\n", status);
return status;
}
- io_buffer_t usb_phy;
- status = io_buffer_init_physical(&usb_phy, bti, 0xd0078000, 4096, get_root_resource(),
+
+ status = io_buffer_init_physical(&reset_buf, bti, S905D2_RESET_BASE, S905D2_RESET_LENGTH,
+ get_root_resource(),
ZX_CACHE_POLICY_UNCACHED_DEVICE);
if (status != ZX_OK) {
zxlogf(ERROR, "aml_usb_init io_buffer_init_physical failed %d\n", status);
@@ -66,45 +71,66 @@
return status;
}
- volatile void* regs = io_buffer_virt(&usb_phy);
-
- // amlogic_new_usb2_init
- for (int i = 0; i < 4; i++) {
- volatile void* addr = regs + (i * PHY_REGISTER_SIZE) + U2P_R0_OFFSET;
- uint32_t temp = readl(addr);
- temp |= U2P_R0_POR;
- temp |= U2P_R0_DMPULLDOWN;
- temp |= U2P_R0_DPPULLDOWN;
- if (i == 1) {
- temp |= U2P_R0_IDPULLUP;
- }
- writel(temp, addr);
- zx_nanosleep(zx_deadline_after(ZX_USEC(500)));
- temp = readl(addr);
- temp &= ~U2P_R0_POR;
- writel(temp, addr);
- }
-
- // amlogic_new_usb3_init
- volatile void* addr = regs + (4 * PHY_REGISTER_SIZE);
-
- uint32_t temp = readl(addr + USB_R1_OFFSET);
- temp = SET_BITS(temp, USB_R1_U3H_FLADJ_30MHZ_REG_START, USB_R1_U3H_FLADJ_30MHZ_REG_BITS, 0x20);
- writel(temp, addr + USB_R1_OFFSET);
-
- temp = readl(addr + USB_R5_OFFSET);
- temp |= USB_R5_IDDIG_EN0;
- temp |= USB_R5_IDDIG_EN1;
- temp = SET_BITS(temp, USB_R5_IDDIG_TH_START, USB_R5_IDDIG_TH_BITS, 255);
- writel(temp, addr + USB_R5_OFFSET);
-
- io_buffer_release(&usb_phy);
- zx_handle_close(bti);
-
- if ((status = pbus_device_add(&bus->pbus, &xhci_dev, 0)) != ZX_OK) {
- zxlogf(ERROR, "aml_usb_init could not add xhci_dev: %d\n", status);
+ status = io_buffer_init_physical(&usbctrl_buf, bti, S905D2_USBCTRL_BASE, S905D2_USBCTRL_LENGTH,
+ get_root_resource(),
+ ZX_CACHE_POLICY_UNCACHED_DEVICE);
+ if (status != ZX_OK) {
+ zxlogf(ERROR, "aml_usb_init io_buffer_init_physical failed %d\n", status);
+ io_buffer_release(&reset_buf);
+ zx_handle_close(bti);
return status;
}
- return ZX_OK;
+ volatile void* reset_regs = io_buffer_virt(&reset_buf);
+ volatile void* usbctrl_regs = io_buffer_virt(&usbctrl_buf);
+
+ // first reset USB
+ uint32_t val = readl(reset_regs + 0x21 * 4);
+ writel((val | (0x3 << 16)), reset_regs + 0x21 * 4);
+
+ volatile uint32_t* reset_1 = (uint32_t *)(reset_regs + S905D2_RESET1_REGISTER);
+ writel(readl(reset_1) | S905D2_RESET1_USB, reset_1);
+ // FIXME(voydanoff) this delay is very long, but it is what the Amlogic Linux kernel is doing.
+ zx_nanosleep(zx_deadline_after(ZX_MSEC(500)));
+
+ // amlogic_new_usb2_init
+ for (int i = 0; i < 2; i++) {
+ volatile void* addr = usbctrl_regs + (i * PHY_REGISTER_SIZE) + U2P_R0_OFFSET;
+ uint32_t temp = readl(addr);
+ temp |= U2P_R0_POR;
+ temp |= U2P_R0_HOST_DEVICE;
+ if (i == 1) {
+ temp |= U2P_R0_IDPULLUP0;
+ temp |= U2P_R0_DRVVBUS0;
+ }
+ writel(temp, addr);
+
+ zx_nanosleep(zx_deadline_after(ZX_USEC(10)));
+
+ writel(readl(reset_1) | (1 << (16 + i)), reset_1);
+
+ zx_nanosleep(zx_deadline_after(ZX_USEC(50)));
+
+ addr = usbctrl_regs + (i * PHY_REGISTER_SIZE) + USB_R1_OFFSET;
+
+ temp = readl(addr);
+ int cnt = 0;
+ while (!(temp & U2P_R1_PHY_RDY)) {
+ temp = readl(addr);
+ //we wait phy ready max 1ms, common is 100us
+ if (cnt > 200) {
+printf("XXXXXX usb loop failed!\n");
+ break;
+ }
+
+ cnt++;
+ zx_nanosleep(zx_deadline_after(ZX_USEC(5)));
+ }
+ }
+
+ io_buffer_release(&reset_buf);
+ io_buffer_release(&usbctrl_buf);
+ zx_handle_close(bti);
+
+ return pbus_device_add(&bus->pbus, &xhci_dev, 0);
}
diff --git a/system/dev/board/aml-s905d2/aml.c b/system/dev/board/aml-s905d2/aml.c
index 13f76f1..9d92a73 100644
--- a/system/dev/board/aml-s905d2/aml.c
+++ b/system/dev/board/aml-s905d2/aml.c
@@ -51,11 +51,11 @@
zxlogf(ERROR, "aml_i2c_init failed: %d\n", status);
goto fail;
}
+*/
if ((status = aml_usb_init(bus)) != ZX_OK) {
zxlogf(ERROR, "aml_usb_init failed: %d\n", status);
goto fail;
}
-*/
return ZX_OK;
fail:
diff --git a/system/dev/soc/amlogic/include/soc/aml-common/aml-usb-phy-v2.h b/system/dev/soc/amlogic/include/soc/aml-common/aml-usb-phy-v2.h
new file mode 100644
index 0000000..ea4d592
--- /dev/null
+++ b/system/dev/soc/amlogic/include/soc/aml-common/aml-usb-phy-v2.h
@@ -0,0 +1,89 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+/*
+// usb2
+phy->regs 0xffe09000 0x80
+phy->reset_regs 0xffd01008 0x4 // used in amlogic_new_usbphy_reset_v2()
+phy->phy_cfg[0] 0xff636000 0x2000
+phy->phy_cfg[1] 0xff63a000 0x2000
+
+ 0x0 0xff636000 0x0 0x2000
+ 0x0 0xff63a000 0x0 0x2000>;
+ pll-setting-1 = <0x09400414>;
+ pll-setting-2 = <0x927E0000>;
+ pll-setting-3 = <0xac5f49e5>;
+
+
+// usb3
+phy->regs = <0x0 0xffe09080 0x0 0x20>;
+phy->phy3_cfg = <0xff646000>; // used in amlogic_new_usb3_v2_probe - set the phy from pcie to usb3
+*/
+
+// size of phy port register block
+#define PHY_REGISTER_SIZE 32
+#define U2P_R0_OFFSET 0x0
+#define U2P_R1_OFFSET 0x4
+
+#define USB_R0_OFFSET 0x80
+#define USB_R1_OFFSET 0x84
+#define USB_R2_OFFSET 0x88
+#define USB_R3_OFFSET 0x8c
+#define USB_R4_OFFSET 0x90
+#define USB_R5_OFFSET 0x94
+
+#define U2P_R0_HOST_DEVICE (1 << 0)
+#define U2P_R0_POWER_OK (1 << 1)
+#define U2P_R0_HOST_MODE (1 << 2)
+#define U2P_R0_POR (1 << 3)
+#define U2P_R0_IDPULLUP0 (1 << 4)
+#define U2P_R0_DRVVBUS0 (1 << 5)
+
+#define U2P_R1_PHY_RDY (1 << 0)
+#define U2P_R1_IDDIG0 (1 << 1)
+#define U2P_R1_OTGSESSVLD0 (1 << 2)
+#define U2P_R1_VBUSVALID0 (1 << 3)
+
+#define USB_R0_P30_LANE0_TX2RX_LOOPBACK (1 << 17)
+#define USB_R0_P30_LANE0_EXT_PCLK_REG (1 << 18)
+#define USB_R0_P30_PCS_RX_LOS_MASK_VAL (1 << 19) // 10 bits
+#define USB_R0_U2D_SS_SCALEDOWN_MODE (1 << 29) // 2 bits
+#define USB_R0_U2D_ACT (1 << 31)
+
+#define USB_R1_U3H_BIGENDIAN_GS (1 << 0)
+#define USB_R1_U3H_PME_EN (1 << 1)
+#define USB_R1_U3H_HUB_PORT_OVERCURRENT (1 << 2) // 3 bits
+#define USB_R1_U3H_HUB_PORT_PERM_ATTACH (1 << 7) // 3 bits
+#define USB_R1_U3H_HOST_U2_PORT_DISABLE (1 << 12) // 2 bits
+#define USB_R1_U3H_HOST_U3_PORT_DISABLE (1 << 16)
+#define USB_R1_U3H_HOST_PORT_POWER_CONTROL_PRESENT (1 << 17)
+#define USB_R1_U3H_HOST_MSI_ENABLE (1 << 18)
+#define USB_R1_U3H_FLADJ_30MHZ_REG (1 << 19) // 6 bits
+#define USB_R1_P30_PCS_TX_SWING_FULL (1 << 25) // 7 bits
+
+#define USB_R2_P30_PCS_TX_DEEMPH_3P5DB (1 << 20) // 6 bits
+#define USB_R2_P30_PCS_TX_DEEMPH_6DB (1 << 26) // 6 bits
+
+#define USB_R3_P30_SSC_EN (1 << 0)
+#define USB_R3_P30_SSC_RANGE (1 << 1) // 3 bits
+#define USB_R3_P30_SSC_REF_CLK_SEL (1 << 4) // 9 bits
+#define USB_R3_P30_REF_SSP_EN (1 << 13)
+
+#define USB_R4_P21_PORTRESET0 (1 << 0)
+#define USB_R4_P21_SLEEPM0 (1 << 1)
+#define USB_R4_MEM_PD (1 << 2) // 2 bits
+#define USB_R4_P21_ONLY (1 << 4)
+
+#define USB_R5_IDDIG_SYNC (1 << 0)
+#define USB_R5_IDDIG_REG (1 << 1)
+#define USB_R5_IDDIG_CFG (1 << 2) // 2 bits
+#define USB_R5_IDDIG_EN0 (1 << 4)
+#define USB_R5_IDDIG_EN1 (1 << 5)
+#define USB_R5_IDDIG_CURR (1 << 6)
+#define USB_R5_USB_IDDIG_IRQ (1 << 7)
+#define USB_R5_IDDIG_TH (1 << 8) // 8 bits
+#define USB_R5_IDDIG_CNT (1 << 16) // 8 bits
+
diff --git a/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h b/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h
index 38d992c..5e13558 100644
--- a/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h
+++ b/system/dev/soc/amlogic/include/soc/aml-s905d2/s905d2-hw.h
@@ -9,6 +9,47 @@
#define S905D2_GPIO_A0_BASE 0xff800000
#define S905D2_GPIO_AO_LENGTH 0x1000
+#define S905D2_USB0_BASE 0xff500000
+#define S905D2_USB0_LENGTH 0x100000
+#define S905D2_USB1_BASE 0xff400000
+#define S905D2_USB1_LENGTH 0x100000
+
+#define S905D2_USBPHY20_BASE 0xff636000
+#define S905D2_USBPHY20_LENGTH 0x2000
+#define S905D2_USBPHY21_BASE 0xff63a000
+#define S905D2_USBPHY21_LENGTH 0x2000
+#define S905D2_USBCTRL_BASE 0xffe09000
+#define S905D2_USBCTRL_LENGTH 0x2000
+
+#define S905D2_RESET_BASE 0xffd01000
+#define S905D2_RESET_LENGTH 0x1000
+
+// Reset register offsets
+#define S905D2_RESET0_REGISTER 0x04
+#define S905D2_RESET1_REGISTER 0x08
+#define S905D2_RESET1_USB (1 << 2) // bit to reset USB
+#define S905D2_RESET2_REGISTER 0x0c
+#define S905D2_RESET3_REGISTER 0x10
+#define S905D2_RESET4_REGISTER 0x14
+#define S905D2_RESET6_REGISTER 0x1c
+#define S905D2_RESET7_REGISTER 0x20
+#define S905D2_RESET0_MASK 0x40
+#define S905D2_RESET1_MASK 0x44
+#define S905D2_RESET2_MASK 0x48
+#define S905D2_RESET3_MASK 0x4c
+#define S905D2_RESET4_MASK 0x50
+#define S905D2_RESET6_MASK 0x58
+#define S905D2_RESET7_MASK 0x5c
+#define S905D2_RESET0_LEVEL 0x80
+#define S905D2_RESET1_LEVEL 0x84
+#define S905D2_RESET2_LEVEL 0x88
+#define S905D2_RESET3_LEVEL 0x8c
+#define S905D2_RESET4_LEVEL 0x90
+#define S905D2_RESET6_LEVEL 0x98
+#define S905D2_RESET7_LEVEL 0x9c
+
+#define S905D2_USBH_IRQ 58
+#define S905D2_USBD_IRQ 59
#define S905D2_GPIO_IRQ_0 94
#define S905D2_GPIO_IRQ_1 95
#define S905D2_GPIO_IRQ_2 96