1/*
2 * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6#include <stdlib.h>
7#include <string.h>
8#include <sel4/types.h>
9
10#include <sel4vm/guest_vm.h>
11#include <sel4vm/guest_memory.h>
12
13#include <sel4vmmplatsupport/guest_memory_util.h>
14#include <sel4vmmplatsupport/plat/usb.h>
15#include <sel4vmmplatsupport/device.h>
16#include <sel4vmmplatsupport/arch/guest_reboot.h>
17#include <utils/io.h>
18
19#define USB2_CONTROLLER_USB2D_USBCMD_0_OFFSET 0x130
20#define USB2D_USB_COMMAND_REGISTER_RESET_BIT BIT(1)
21
22const struct device dev_usb = {
23    .name = "usb",
24    .pstart = 0x7d004000,
25    .size = PAGE_SIZE,
26    .priv = NULL
27};
28
29static int usb_vm_reboot_hook(vm_t *vm, void *token)
30{
31    void *usb_cmd_register = token + USB2_CONTROLLER_USB2D_USBCMD_0_OFFSET;
32    uint32_t reg = RAW_READ32(usb_cmd_register);
33    RAW_WRITE32(reg | USB2D_USB_COMMAND_REGISTER_RESET_BIT, usb_cmd_register);
34    return 0;
35}
36
37
38static memory_fault_result_t handle_usb_fault(vm_t *vm, vm_vcpu_t *vcpu, uintptr_t fault_addr, size_t fault_length,
39                                              void *cookie)
40{
41    ZF_LOGE("Fault occured on passthrough usb device");
42    return FAULT_ERROR;
43}
44
45int vm_install_tk1_usb_passthrough_device(vm_t *vm, reboot_hooks_list_t *reboot_hooks)
46{
47    /* Add the device */
48    void *vmm_addr = create_device_reservation_frame(vm, dev_usb.pstart, seL4_AllRights, handle_usb_fault, NULL);
49    if (vmm_addr == NULL) {
50        ZF_LOGE("Failed to create passthrough usb device");
51        return -1;
52    }
53
54    int err = vmm_register_reboot_callback(reboot_hooks, usb_vm_reboot_hook, vmm_addr);
55    if (err) {
56        ZF_LOGE("vm_register_reboot_callback returned error: %d", err);
57        return -1;
58    }
59
60    return 0;
61}
62