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