1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <ddk/debug.h>
6 #include <ddk/device.h>
7 #include <ddk/platform-defs.h>
8 #include <ddktl/mmio.h>
9 #include <hw/reg.h>
10 #include <lib/zx/handle.h>
11 #include <soc/aml-common/aml-usb-phy-v2.h>
12
13 #include <soc/aml-t931/t931-gpio.h>
14 #include <soc/aml-t931/t931-hw.h>
15
16 #include <optional>
17
18 #include "sherlock.h"
19
20 namespace sherlock {
21
22 namespace {
23
24 constexpr pbus_mmio_t xhci_mmios[] = {
25 {
26 .base = T931_USB0_BASE,
27 .length = T931_USB0_LENGTH,
28 },
29 };
30
31 constexpr pbus_irq_t xhci_irqs[] = {
32 {
33 .irq = T931_USB0_IRQ,
34 .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
35 },
36 };
37
38 constexpr pbus_bti_t xhci_btis[] = {
39 {
40 .iommu_index = 0,
41 .bti_id = BTI_USB_XHCI,
42 },
43 };
44
__anon8bc38fb10202()45 static pbus_dev_t xhci_dev = [](){
46 pbus_dev_t dev;
47 dev.name = "xhci";
48 dev.vid = PDEV_VID_GENERIC;
49 dev.pid = PDEV_PID_GENERIC;
50 dev.did = PDEV_DID_USB_XHCI;
51 dev.mmio_list = xhci_mmios;
52 dev.mmio_count = countof(xhci_mmios);
53 dev.irq_list = xhci_irqs;
54 dev.irq_count = countof(xhci_irqs);
55 dev.bti_list = xhci_btis;
56 dev.bti_count = countof(xhci_btis);
57 return dev;
58 }();
59
60 // magic numbers for USB PHY tuning
61 constexpr uint32_t PLL_SETTING_3 = 0xfe18;
62 constexpr uint32_t PLL_SETTING_4 = 0xfff;
63 constexpr uint32_t PLL_SETTING_5 = 0xc8000;
64 constexpr uint32_t PLL_SETTING_6 = 0xe0004;
65 constexpr uint32_t PLL_SETTING_7 = 0xe000c;
66
PerformUsbTuning(bool host,bool default_val)67 zx_status_t PerformUsbTuning(bool host, bool default_val) {
68 std::optional<ddk::MmioBuffer> buf;
69 zx_status_t status;
70
71 zx::unowned_resource resource(get_root_resource());
72 status = ddk::MmioBuffer::Create(T931_USBPHY21_BASE, T931_USBPHY21_LENGTH, *resource,
73 ZX_CACHE_POLICY_UNCACHED_DEVICE, &buf);
74 if (status != ZX_OK) {
75 return status;
76 }
77
78 if (default_val) {
79 buf->Write32(0, 0x38);
80 buf->Write32(PLL_SETTING_5, 0x34);
81 } else {
82 buf->Write32(PLL_SETTING_3, 0x50);
83 buf->Write32(PLL_SETTING_4, 0x10);
84 if (host) {
85 buf->Write32(PLL_SETTING_6, 0x38);
86 } else {
87 buf->Write32(PLL_SETTING_7, 0x38);
88 }
89 buf->Write32(PLL_SETTING_5, 0x34);
90 }
91
92 return ZX_OK;
93 }
94
95 } // namespace
96
UsbInit()97 zx_status_t Sherlock::UsbInit() {
98 zx::bti bti;
99 auto status = iommu_.GetBti(BTI_BOARD, 0, &bti);
100 if (status != ZX_OK) {
101 zxlogf(ERROR, "%s: GetBti failed: %d\n", __func__, status);
102 return status;
103 }
104
105 status = aml_usb_phy_v2_init(bti.get());
106 if (status != ZX_OK) {
107 zxlogf(ERROR, "%s: aml_usb_phy_v2_init failed %d\n", __func__, status);
108 return status;
109 }
110
111 status = PerformUsbTuning(true, false);
112 if (status != ZX_OK) {
113 return status;
114 }
115
116 status = pbus_.DeviceAdd(&xhci_dev);
117 if (status != ZX_OK) {
118 zxlogf(ERROR, "%s: DeviceAdd failed %d\n", __func__, status);
119 return status;
120 }
121
122 return ZX_OK;
123 }
124
125 } // namespace sherlock
126