| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <lib/mmio/mmio.h> |
| #include <lib/zx/resource.h> |
| |
| #include <ddk/debug.h> |
| #include <ddk/platform-defs.h> |
| #include <soc/aml-common/aml-usb-phy.h> |
| #include <soc/aml-s912/s912-hw.h> |
| |
| #include "vim.h" |
| |
| namespace vim { |
| #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 = S912_USB0_BASE, |
| .length = S912_USB0_LENGTH, |
| }, |
| }; |
| |
| static const pbus_irq_t xhci_irqs[] = { |
| { |
| .irq = S912_USBH_IRQ, |
| .mode = ZX_INTERRUPT_MODE_EDGE_HIGH, |
| }, |
| }; |
| |
| static const pbus_bti_t xhci_btis[] = { |
| { |
| .iommu_index = 0, |
| .bti_id = BTI_USB_XHCI, |
| }, |
| }; |
| |
| zx_status_t Vim::UsbInit() { |
| zx_status_t status; |
| pbus_dev_t xhci_dev = {}; |
| |
| xhci_dev.name = "xhci"; |
| xhci_dev.vid = PDEV_VID_GENERIC; |
| xhci_dev.pid = PDEV_PID_GENERIC; |
| xhci_dev.did = PDEV_DID_USB_XHCI; |
| xhci_dev.mmio_list = xhci_mmios; |
| xhci_dev.mmio_count = countof(xhci_mmios); |
| xhci_dev.irq_list = xhci_irqs; |
| xhci_dev.irq_count = countof(xhci_irqs); |
| xhci_dev.bti_list = xhci_btis; |
| xhci_dev.bti_count = countof(xhci_btis); |
| |
| zx::bti bti; |
| |
| std::optional<ddk::MmioBuffer> usb_phy; |
| // Please do not use get_root_resource() in new code. See fxbug.dev/31358. |
| zx::unowned_resource resource(get_root_resource()); |
| status = ddk::MmioBuffer::Create(S912_USB_PHY_BASE, S912_USB_PHY_LENGTH, *resource, |
| ZX_CACHE_POLICY_UNCACHED_DEVICE, &usb_phy); |
| if (status != ZX_OK) { |
| zxlogf(ERROR, "UsbInit io_buffer_init_physical failed %d", status); |
| return status; |
| } |
| |
| MMIO_PTR volatile auto* regs = static_cast<MMIO_PTR uint32_t*>(usb_phy->get()); |
| |
| // amlogic_new_usb2_init |
| for (int i = 0; i < 4; i++) { |
| MMIO_PTR volatile auto* addr = |
| regs + (i * PHY_REGISTER_SIZE / sizeof(uint32_t)) + U2P_R0_OFFSET; |
| |
| uint32_t temp = MmioRead32(addr); |
| temp |= U2P_R0_POR; |
| temp |= U2P_R0_DMPULLDOWN; |
| temp |= U2P_R0_DPPULLDOWN; |
| if (i == 1) { |
| temp |= U2P_R0_IDPULLUP; |
| } |
| MmioWrite32(temp, addr); |
| zx_nanosleep(zx_deadline_after(ZX_USEC(500))); |
| temp = MmioRead32(addr); |
| temp &= ~U2P_R0_POR; |
| MmioWrite32(temp, addr); |
| } |
| |
| // amlogic_new_usb3_init |
| MMIO_PTR volatile auto* addr = regs + (4 * PHY_REGISTER_SIZE / sizeof(uint32_t)); |
| |
| uint32_t temp = MmioRead32(addr + USB_R1_OFFSET); |
| temp = SET_BITS(temp, USB_R1_U3H_FLADJ_30MHZ_REG_START, USB_R1_U3H_FLADJ_30MHZ_REG_BITS, 0x20); |
| MmioWrite32(temp, addr + USB_R1_OFFSET); |
| |
| temp = MmioRead32(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); |
| MmioWrite32(temp, addr + USB_R5_OFFSET); |
| |
| if ((status = pbus_.DeviceAdd(&xhci_dev)) != ZX_OK) { |
| zxlogf(ERROR, "UsbInit could not add xhci_dev: %d", status); |
| return status; |
| } |
| |
| return ZX_OK; |
| } |
| } // namespace vim |