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/mmio-buffer.h>
7 #include <ddk/platform-defs.h>
8 #include <hw/reg.h>
9 #include <soc/aml-common/aml-usb-phy-v2.h>
10 #include <soc/aml-s905d2/s905d2-hw.h>
11 
12 #include "astro.h"
13 
14 static const pbus_mmio_t xhci_mmios[] = {
15     {
16         .base = S905D2_USB0_BASE,
17         .length = S905D2_USB0_LENGTH,
18     },
19 };
20 
21 static const pbus_irq_t xhci_irqs[] = {
22     {
23         .irq = S905D2_USB0_IRQ,
24         .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
25     },
26 };
27 
28 static const pbus_bti_t xhci_btis[] = {
29     {
30         .iommu_index = 0,
31         .bti_id = BTI_USB_XHCI,
32     },
33 };
34 
35 static const pbus_dev_t xhci_dev = {
36     .name = "xhci",
37     .vid = PDEV_VID_GENERIC,
38     .pid = PDEV_PID_GENERIC,
39     .did = PDEV_DID_USB_XHCI,
40     .mmio_list = xhci_mmios,
41     .mmio_count = countof(xhci_mmios),
42     .irq_list = xhci_irqs,
43     .irq_count = countof(xhci_irqs),
44     .bti_list = xhci_btis,
45     .bti_count = countof(xhci_btis),
46 };
47 
48 // magic numbers for USB PHY tuning
49 #define PLL_SETTING_3   0xfe18
50 #define PLL_SETTING_4   0xfff
51 #define PLL_SETTING_5   0x78000
52 #define PLL_SETTING_6   0xe0004
53 #define PLL_SETTING_7   0xe000c
54 
astro_usb_tuning(bool host,bool default_val)55 static zx_status_t astro_usb_tuning(bool host, bool default_val) {
56     mmio_buffer_t buf;
57     zx_status_t status;
58 
59     status = mmio_buffer_init_physical(&buf, S905D2_USBPHY21_BASE, S905D2_USBPHY21_LENGTH,
60                                        get_root_resource(), ZX_CACHE_POLICY_UNCACHED_DEVICE);
61     if (status != ZX_OK) {
62         return status;
63     }
64 
65     volatile void* base = buf.vaddr;
66 
67     if (default_val) {
68         writel(0, base + 0x38);
69         writel(PLL_SETTING_5, base + 0x34);
70     } else {
71         writel(PLL_SETTING_3, base + 0x50);
72         writel(PLL_SETTING_4, base + 0x10);
73         if (host) {
74             writel(PLL_SETTING_6, base + 0x38);
75         } else {
76             writel(PLL_SETTING_7, base + 0x38);
77         }
78         writel(PLL_SETTING_5, base + 0x34);
79     }
80 
81     mmio_buffer_release(&buf);
82     return ZX_OK;
83 }
84 
aml_usb_init(aml_bus_t * bus)85 zx_status_t aml_usb_init(aml_bus_t* bus) {
86     zx_handle_t bti;
87 
88     zx_status_t status = iommu_get_bti(&bus->iommu, 0, BTI_BOARD, &bti);
89     if (status != ZX_OK) {
90         zxlogf(ERROR, "aml_usb_init: iommu_get_bti failed: %d\n", status);
91         return status;
92     }
93 
94     status = aml_usb_phy_v2_init(bti);
95     if (status != ZX_OK) {
96         return status;
97     }
98 
99     status = astro_usb_tuning(true, false);
100     zx_handle_close(bti);
101     if (status != ZX_OK) {
102         return status;
103     }
104 
105     return pbus_device_add(&bus->pbus, &xhci_dev);
106 }
107