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