[astro][usb] USB PHY tuning hack
Change-Id: Ib0a02b6b136e260a034b93935779031ae9f997f2
diff --git a/system/dev/board/astro/astro-usb.c b/system/dev/board/astro/astro-usb.c
index 1d4ca42..4af8bb4 100644
--- a/system/dev/board/astro/astro-usb.c
+++ b/system/dev/board/astro/astro-usb.c
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <ddk/debug.h>
+#include <ddk/protocol/astro-usb.h>
#include <ddk/protocol/platform-defs.h>
#include <hw/reg.h>
#include <soc/aml-common/aml-usb-phy-v2.h>
@@ -51,19 +52,18 @@
#define PLL_SETTING_6 0xe0004
#define PLL_SETTING_7 0xe000c
-static zx_status_t astro_usb_tuning(zx_handle_t bti, bool host, bool default_val) {
- io_buffer_t buf;
- zx_status_t status;
+static zx_status_t astro_do_usb_tuning(void* ctx, bool set_default) {
+ aml_bus_t* bus = ctx;
+ volatile void* base = io_buffer_virt(&bus->usb_tuning_buf);
+ const bool host = true;
- status = io_buffer_init_physical(&buf, bti, S905D2_USBPHY21_BASE, S905D2_USBPHY21_LENGTH,
- get_root_resource(), ZX_CACHE_POLICY_UNCACHED_DEVICE);
- if (status != ZX_OK) {
- return status;
+ zxlogf(INFO, "astro_do_usb_tuning set_default: %s\n", (set_default ? "true" : "false"));
+
+ if (bus->cur_usb_tuning == !!set_default) {
+ return ZX_OK;
}
- volatile void* base = io_buffer_virt(&buf);
-
- if (default_val) {
+ if (set_default) {
writel(0, base + 0x38);
writel(PLL_SETTING_5, base + 0x34);
} else {
@@ -77,10 +77,14 @@
writel(PLL_SETTING_5, base + 0x34);
}
- io_buffer_release(&buf);
+ bus->cur_usb_tuning = !!set_default;
return ZX_OK;
}
+astro_usb_protocol_ops_t astro_usb_ops = {
+ .do_usb_tuning = astro_do_usb_tuning,
+};
+
zx_status_t aml_usb_init(aml_bus_t* bus) {
zx_handle_t bti;
@@ -95,11 +99,20 @@
return status;
}
- status = astro_usb_tuning(bti, true, false);
+ status = io_buffer_init_physical(&bus->usb_tuning_buf, bti, S905D2_USBPHY21_BASE,
+ S905D2_USBPHY21_LENGTH, get_root_resource(),
+ ZX_CACHE_POLICY_UNCACHED_DEVICE);
zx_handle_close(bti);
if (status != ZX_OK) {
return status;
}
+ bus->cur_usb_tuning = -1;
+
+ astro_usb_protocol_t astro_usb = {
+ .ops = &astro_usb_ops,
+ .ctx = bus,
+ };
+ pbus_set_protocol(&bus->pbus, ZX_PROTOCOL_ASTRO_USB, &astro_usb);
return pbus_device_add(&bus->pbus, &xhci_dev, 0);
}
diff --git a/system/dev/board/astro/astro.h b/system/dev/board/astro/astro.h
index 1cadfa8..82244d7 100644
--- a/system/dev/board/astro/astro.h
+++ b/system/dev/board/astro/astro.h
@@ -30,6 +30,8 @@
serial_impl_protocol_t serial;
zx_device_t* parent;
iommu_protocol_t iommu;
+ io_buffer_t usb_tuning_buf;
+ int cur_usb_tuning;
} aml_bus_t;
// astro-gpio.c
diff --git a/system/dev/bus/platform/platform-bus.c b/system/dev/bus/platform/platform-bus.c
index 2a03115..794df85 100644
--- a/system/dev/bus/platform/platform-bus.c
+++ b/system/dev/bus/platform/platform-bus.c
@@ -65,6 +65,9 @@
case ZX_PROTOCOL_SCPI:
memcpy(&bus->scpi, protocol, sizeof(bus->scpi));
break;
+ case ZX_PROTOCOL_ASTRO_USB:
+ memcpy(&bus->astro_usb, protocol, sizeof(bus->astro_usb));
+ break;
default:
// TODO(voydanoff) consider having a registry of arbitrary protocols
return ZX_ERR_NOT_SUPPORTED;
diff --git a/system/dev/bus/platform/platform-bus.h b/system/dev/bus/platform/platform-bus.h
index a99fd74..4fa294b 100644
--- a/system/dev/bus/platform/platform-bus.h
+++ b/system/dev/bus/platform/platform-bus.h
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <threads.h>
#include <ddk/device.h>
+#include <ddk/protocol/astro-usb.h>
#include <ddk/protocol/clk.h>
#include <ddk/protocol/gpio.h>
#include <ddk/protocol/i2c.h>
@@ -35,6 +36,7 @@
i2c_impl_protocol_t i2c;
clk_protocol_t clk;
iommu_protocol_t iommu;
+ astro_usb_protocol_t astro_usb;
zx_handle_t resource; // root resource for platform bus
zbi_platform_id_t platform_id;
uint8_t* metadata; // metadata extracted from ZBI
diff --git a/system/dev/bus/platform/platform-device.c b/system/dev/bus/platform/platform-device.c
index c67c2dc..5b4c31a 100644
--- a/system/dev/bus/platform/platform-device.c
+++ b/system/dev/bus/platform/platform-device.c
@@ -343,6 +343,14 @@
return scpi_set_dvfs_idx(&bus->scpi, power_domain, idx);
}
+static zx_status_t pdev_rpc_astro_do_usb_tuning(platform_dev_t* dev, bool set_default) {
+ platform_bus_t* bus = dev->bus;
+ if (!bus->astro_usb.ops) {
+ return ZX_ERR_NOT_SUPPORTED;
+ }
+ return astro_usb_do_usb_tuning(&bus->astro_usb, set_default);
+}
+
static zx_status_t pdev_rpc_i2c_transact(platform_dev_t* dev, pdev_req_t* req, uint8_t* data,
zx_handle_t channel) {
platform_bus_t* bus = dev->bus;
@@ -478,6 +486,10 @@
resp.status = pdev_rpc_scpi_set_dvfs_idx(dev, req->scpi.power_domain,
req->scpi.idx);
break;
+
+ case PDEV_ASTRO_USB_TUNING:
+ resp.status = pdev_rpc_astro_do_usb_tuning(dev, req->index);
+ break;
case PDEV_I2C_GET_MAX_TRANSFER:
resp.status = i2c_impl_get_max_transfer_size(&dev->bus->i2c, req->index,
&resp.i2c_max_transfer);
diff --git a/system/dev/bus/platform/platform-proxy.c b/system/dev/bus/platform/platform-proxy.c
index 9e10162..57819bf 100644
--- a/system/dev/bus/platform/platform-proxy.c
+++ b/system/dev/bus/platform/platform-proxy.c
@@ -16,6 +16,7 @@
#include <ddk/protocol/platform-device.h>
#include <ddk/protocol/clk.h>
#include <ddk/protocol/usb-mode-switch.h>
+#include <ddk/protocol/astro-usb.h>
#include "platform-proxy.h"
@@ -304,6 +305,22 @@
.set_dvfs_idx = pdev_scpi_set_dvfs_idx,
};
+static zx_status_t pdev_astro_do_usb_tuning(void* ctx, bool set_default) {
+ platform_proxy_t* proxy = ctx;
+ pdev_req_t req = {
+ .op = PDEV_ASTRO_USB_TUNING,
+ .index = set_default,
+ };
+
+ pdev_resp_t resp;
+ return platform_dev_rpc(proxy, &req, sizeof(req), &resp, sizeof(resp),
+ NULL, 0, NULL, 0, NULL);
+}
+
+static astro_usb_protocol_ops_t astro_usb_ops = {
+ .do_usb_tuning = pdev_astro_do_usb_tuning,
+};
+
static zx_status_t pdev_mailbox_send_cmd(void* ctx, mailbox_channel_t* channel,
mailbox_data_buf_t* mdata) {
platform_proxy_t* proxy = ctx;
@@ -618,6 +635,12 @@
proto->ops = &scpi_ops;
return ZX_OK;
}
+ case ZX_PROTOCOL_ASTRO_USB: {
+ astro_usb_protocol_t* proto = out;
+ proto->ctx = ctx;
+ proto->ops = &astro_usb_ops;
+ return ZX_OK;
+ }
default:
return ZX_ERR_NOT_SUPPORTED;
}
diff --git a/system/dev/bus/platform/platform-proxy.h b/system/dev/bus/platform/platform-proxy.h
index fbe39f9..d46bf89 100644
--- a/system/dev/bus/platform/platform-proxy.h
+++ b/system/dev/bus/platform/platform-proxy.h
@@ -53,6 +53,9 @@
PDEV_SCPI_GET_DVFS_INFO,
PDEV_SCPI_GET_DVFS_IDX,
PDEV_SCPI_SET_DVFS_IDX,
+
+ // ZX_PROTOCOL_ASTRO_USB
+ PDEV_ASTRO_USB_TUNING,
};
// context for mailbox
diff --git a/system/dev/usb/xhci/usb-xhci.c b/system/dev/usb/xhci/usb-xhci.c
index 7a9b4eb..9c1c532 100644
--- a/system/dev/usb/xhci/usb-xhci.c
+++ b/system/dev/usb/xhci/usb-xhci.c
@@ -437,6 +437,9 @@
goto error_return;
}
+ // hack for astro USB tuning
+ device_get_protocol(parent, ZX_PROTOCOL_ASTRO_USB, &xhci->astro_usb);
+
status = pdev_get_bti(pdev, 0, &xhci->bti_handle);
if (status != ZX_OK) {
goto error_return;
diff --git a/system/dev/usb/xhci/xhci-root-hub.c b/system/dev/usb/xhci/xhci-root-hub.c
index a9a4d44..8eaaff8 100644
--- a/system/dev/usb/xhci/xhci-root-hub.c
+++ b/system/dev/usb/xhci/xhci-root-hub.c
@@ -401,6 +401,11 @@
usb_request_complete(req, ZX_OK, 0);
return ZX_OK;
} else if (value == USB_FEATURE_PORT_RESET) {
+ // hack for astro USB tuning
+ if (xhci->astro_usb.ops) {
+ astro_usb_do_usb_tuning(&xhci->astro_usb, true);
+ }
+
xhci_reset_port(xhci, rh, rh_port_index);
usb_request_complete(req, ZX_OK, 0);
return ZX_OK;
@@ -422,6 +427,10 @@
*change_bits &= ~USB_C_PORT_OVER_CURRENT;
break;
case USB_FEATURE_C_PORT_RESET:
+ // hack for astro USB tuning
+ if (xhci->astro_usb.ops) {
+ astro_usb_do_usb_tuning(&xhci->astro_usb, false);
+ }
*change_bits &= ~USB_C_PORT_RESET;
break;
}
diff --git a/system/dev/usb/xhci/xhci.h b/system/dev/usb/xhci/xhci.h
index f12ffd0..bebba7e 100644
--- a/system/dev/usb/xhci/xhci.h
+++ b/system/dev/usb/xhci/xhci.h
@@ -14,6 +14,7 @@
#include <threads.h>
#include <ddk/device.h>
+#include <ddk/protocol/astro-usb.h>
#include <ddk/protocol/pci.h>
#include <ddk/protocol/platform-device.h>
#include <ddk/protocol/usb-bus.h>
@@ -124,6 +125,9 @@
// platform device support
platform_device_protocol_t* pdev;
+ // hack for astro USB tuning
+ astro_usb_protocol_t astro_usb;
+
// MMIO data structures
xhci_cap_regs_t* cap_regs;
xhci_op_regs_t* op_regs;
diff --git a/system/ulib/ddk/include/ddk/protocol/astro-usb.h b/system/ulib/ddk/include/ddk/protocol/astro-usb.h
new file mode 100644
index 0000000..31e8b37
--- /dev/null
+++ b/system/ulib/ddk/include/ddk/protocol/astro-usb.h
@@ -0,0 +1,25 @@
+// Copyright 2018 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <zircon/compiler.h>
+#include <zircon/types.h>
+
+__BEGIN_CDECLS;
+
+typedef struct {
+ zx_status_t (*do_usb_tuning)(void* ctx, bool set_default);
+} astro_usb_protocol_ops_t;
+
+typedef struct {
+ astro_usb_protocol_ops_t* ops;
+ void* ctx;
+} astro_usb_protocol_t;
+
+static inline zx_status_t astro_usb_do_usb_tuning(astro_usb_protocol_t* usb, bool set_default) {
+ return usb->ops->do_usb_tuning(usb->ctx, set_default);
+}
+
+__END_CDECLS;
diff --git a/system/ulib/ddk/include/ddk/protodefs.h b/system/ulib/ddk/include/ddk/protodefs.h
index 2fd3253..6318b35 100644
--- a/system/ulib/ddk/include/ddk/protodefs.h
+++ b/system/ulib/ddk/include/ddk/protodefs.h
@@ -82,6 +82,8 @@
DDK_PROTOCOL_DEF(MAILBOX, 'pMHU', "mailbox", 0)
DDK_PROTOCOL_DEF(SCPI, 'pSCP', "scpi", 0)
DDK_PROTOCOL_DEF(BACKLIGHT, 'pBKL', "backlight", 0)
+DDK_PROTOCOL_DEF(ASTRO_USB, 'pAUX', "astro-usb", PF_NOPUB)
+
// Protocol definition at garnet/magma/src/magma_util/platform/zircon/zircon_platform_ioctl.h
DDK_PROTOCOL_DEF(GPU, 'pGPU', "gpu", 0)
DDK_PROTOCOL_DEF(RTC, 'pRTC', "rtc", 0)