1 // Copyright 2017 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/platform-defs.h>
7 #include <hw/reg.h>
8
9 #include <soc/aml-common/aml-usb-phy.h>
10 #include <soc/aml-s912/s912-hw.h>
11
12 #include "vim.h"
13
14 #define BIT_MASK(start, count) (((1 << (count)) - 1) << (start))
15 #define SET_BITS(dest, start, count, value) \
16 ((dest & ~BIT_MASK(start, count)) | (((value) << (start)) & BIT_MASK(start, count)))
17
18 static const pbus_mmio_t xhci_mmios[] = {
19 {
20 .base = S912_USB0_BASE,
21 .length = S912_USB0_LENGTH,
22 },
23 };
24
25 static const pbus_irq_t xhci_irqs[] = {
26 {
27 .irq = S912_USBH_IRQ,
28 .mode = ZX_INTERRUPT_MODE_EDGE_HIGH,
29 },
30 };
31
32 static const pbus_bti_t xhci_btis[] = {
33 {
34 .iommu_index = 0,
35 .bti_id = BTI_USB_XHCI,
36 },
37 };
38
39 static const pbus_dev_t xhci_dev = {
40 .name = "xhci",
41 .vid = PDEV_VID_GENERIC,
42 .pid = PDEV_PID_GENERIC,
43 .did = PDEV_DID_USB_XHCI,
44 .mmio_list = xhci_mmios,
45 .mmio_count = countof(xhci_mmios),
46 .irq_list = xhci_irqs,
47 .irq_count = countof(xhci_irqs),
48 .bti_list = xhci_btis,
49 .bti_count = countof(xhci_btis),
50 };
51
vim_usb_init(vim_bus_t * bus)52 zx_status_t vim_usb_init(vim_bus_t* bus) {
53 zx_status_t status;
54
55 zx_handle_t bti;
56 status = iommu_get_bti(&bus->iommu, 0, BTI_BOARD, &bti);
57 if (status != ZX_OK) {
58 zxlogf(ERROR, "vim_bus_bind: iommu_get_bti failed: %d\n", status);
59 return status;
60 }
61 io_buffer_t usb_phy;
62 status = io_buffer_init_physical(&usb_phy, bti, S912_USB_PHY_BASE, S912_USB_PHY_LENGTH,
63 get_root_resource(),
64 ZX_CACHE_POLICY_UNCACHED_DEVICE);
65 if (status != ZX_OK) {
66 zxlogf(ERROR, "vim_usb_init io_buffer_init_physical failed %d\n", status);
67 zx_handle_close(bti);
68 return status;
69 }
70
71 volatile void* regs = io_buffer_virt(&usb_phy);
72
73 // amlogic_new_usb2_init
74 for (int i = 0; i < 4; i++) {
75 volatile void* addr = regs + (i * PHY_REGISTER_SIZE) + U2P_R0_OFFSET;
76 uint32_t temp = readl(addr);
77 temp |= U2P_R0_POR;
78 temp |= U2P_R0_DMPULLDOWN;
79 temp |= U2P_R0_DPPULLDOWN;
80 if (i == 1) {
81 temp |= U2P_R0_IDPULLUP;
82 }
83 writel(temp, addr);
84 zx_nanosleep(zx_deadline_after(ZX_USEC(500)));
85 temp = readl(addr);
86 temp &= ~U2P_R0_POR;
87 writel(temp, addr);
88 }
89
90 // amlogic_new_usb3_init
91 volatile void* addr = regs + (4 * PHY_REGISTER_SIZE);
92
93 uint32_t temp = readl(addr + USB_R1_OFFSET);
94 temp = SET_BITS(temp, USB_R1_U3H_FLADJ_30MHZ_REG_START, USB_R1_U3H_FLADJ_30MHZ_REG_BITS, 0x20);
95 writel(temp, addr + USB_R1_OFFSET);
96
97 temp = readl(addr + USB_R5_OFFSET);
98 temp |= USB_R5_IDDIG_EN0;
99 temp |= USB_R5_IDDIG_EN1;
100 temp = SET_BITS(temp, USB_R5_IDDIG_TH_START, USB_R5_IDDIG_TH_BITS, 255);
101 writel(temp, addr + USB_R5_OFFSET);
102
103 io_buffer_release(&usb_phy);
104 zx_handle_close(bti);
105
106 if ((status = pbus_device_add(&bus->pbus, &xhci_dev)) != ZX_OK) {
107 zxlogf(ERROR, "vim_usb_init could not add xhci_dev: %d\n", status);
108 return status;
109 }
110
111 return ZX_OK;
112 }
113