// Copyright 2017 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.

#include <ddk/binding.h>
#include <ddk/debug.h>
#include <ddk/platform-defs.h>
#include <ddk/protocol/usb-function.h>
#include <usb/usb-request.h>
#include <fbl/auto_lock.h>
#include <hw/reg.h>
#include <pretty/hexdump.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "dwc3.h"
#include "dwc3-regs.h"
#include "dwc3-types.h"

// MMIO indices
enum {
    MMIO_USB3OTG,
};

// IRQ indices
enum {
    IRQ_USB3,
};

void dwc3_print_status(dwc3_t* dwc) {
    auto* mmio = dwc3_mmio(dwc);
    auto dsts = DSTS::Get().ReadFrom(mmio);
    zxlogf(TRACE, "DSTS: ");
    zxlogf(TRACE, "USBLNKST: %d ", dsts.USBLNKST());
    zxlogf(TRACE, "SOFFN: %d ", dsts.SOFFN());
    zxlogf(TRACE, "CONNECTSPD: %d ", dsts.CONNECTSPD());
    if (dsts.DCNRD()) zxlogf(TRACE, "DCNRD ");
    if (dsts.SRE()) zxlogf(TRACE, "SRE ");
    if (dsts.RSS()) zxlogf(TRACE, "RSS ");
    if (dsts.SSS()) zxlogf(TRACE, "SSS ");
    if (dsts.COREIDLE()) zxlogf(TRACE, "COREIDLE ");
    if (dsts.DEVCTRLHLT()) zxlogf(TRACE, "DEVCTRLHLT ");
    if (dsts.RXFIFOEMPTY()) zxlogf(TRACE, "RXFIFOEMPTY ");
    zxlogf(TRACE, "\n");

    auto gsts = GSTS::Get().ReadFrom(mmio);
    zxlogf(TRACE, "GSTS: ");
    zxlogf(TRACE, "CBELT: %d ", gsts.CBELT());
    zxlogf(TRACE, "CURMOD: %d ", gsts.CURMOD());
    if (gsts.SSIC_IP()) zxlogf(TRACE, "SSIC_IP ");
    if (gsts.OTG_IP()) zxlogf(TRACE, "OTG_IP ");
    if (gsts.BC_IP()) zxlogf(TRACE, "BC_IP ");
    if (gsts.ADP_IP()) zxlogf(TRACE, "ADP_IP ");
    if (gsts.Host_IP()) zxlogf(TRACE, "HOST_IP ");
    if (gsts.Device_IP()) zxlogf(TRACE, "DEVICE_IP ");
    if (gsts.CSRTimeout()) zxlogf(TRACE, "CSR_TIMEOUT ");
    if (gsts.BUSERRADDRVLD()) zxlogf(TRACE, "BUSERRADDRVLD ");
    zxlogf(TRACE, "\n");
}

static void dwc3_stop(dwc3_t* dwc) {
    auto* mmio = dwc3_mmio(dwc);

    fbl::AutoLock lock(&dwc->lock);

    DCTL::Get()
        .ReadFrom(mmio)
        .set_RUN_STOP(0)
        .set_CSFTRST(1)
        .WriteTo(mmio);
    while (DCTL::Get().ReadFrom(mmio).CSFTRST()) {
        usleep(1000);
    }
}

static void dwc3_start_peripheral_mode(dwc3_t* dwc) {
    auto* mmio = dwc3_mmio(dwc);

    dwc->lock.Acquire();

    // configure and enable PHYs
    GUSB2PHYCFG::Get(0).ReadFrom(mmio).set_USBTRDTIM(9).WriteTo(mmio);
    GUSB3PIPECTL::Get(0)
        .ReadFrom(mmio)
        .set_DELAYP1TRANS(0)
        .set_SUSPENDENABLE(0)
        .set_LFPSFILTER(1)
        .set_SS_TX_DE_EMPHASIS(1)
        .WriteTo(mmio);

    // configure for device mode
    GCTL::Get()
        .FromValue(0)
        .set_PWRDNSCALE(2)
        .set_U2RSTECN(1)
        .set_PRTCAPDIR(GCTL::PRTCAPDIR_DEVICE)
        .set_U2EXIT_LFPS(1)
        .WriteTo(mmio);

    uint32_t nump = 16;
    uint32_t max_speed = DCFG::DEVSPD_SUPER;
    DCFG::Get()
        .ReadFrom(mmio)
        .set_NUMP(nump)
        .set_DEVSPD(max_speed)
        .set_DEVADDR(0)
        .WriteTo(mmio);

    dwc3_events_start(dwc);

    dwc->lock.Release();

    dwc3_ep0_start(dwc);

    dwc->lock.Acquire();

    // start the controller
    DCTL::Get().FromValue(0).set_RUN_STOP(1).WriteTo(mmio);

    dwc->lock.Release();
}

static zx_status_t xhci_get_protocol(void* ctx, uint32_t proto_id, void* protocol) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    // XHCI uses same MMIO and IRQ as dwc3, so we can just share our pdev protoocl
    // with the XHCI driver
    return device_get_protocol(dwc->parent, proto_id, protocol);
}

static void xhci_release(void* ctx) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    fbl::AutoLock lock(&dwc->usb_mode_lock);

    if (dwc->start_device_on_xhci_release) {
        dwc3_start_peripheral_mode(dwc);
        dwc->start_device_on_xhci_release = false;
        dwc->usb_mode = USB_MODE_PERIPHERAL;
    }
}

static zx_protocol_device_t xhci_device_ops = []() {
    zx_protocol_device_t device;
    device.version = DEVICE_OPS_VERSION;
    device.get_protocol = xhci_get_protocol;
    device.release = xhci_release;
    return device;
}();

static void dwc3_start_host_mode(dwc3_t* dwc) {
    auto* mmio = dwc3_mmio(dwc);

    dwc->lock.Acquire();

    // configure for host mode
    GCTL::Get()
        .FromValue(0)
        .set_PWRDNSCALE(2)
        .set_U2RSTECN(1)
        .set_PRTCAPDIR(GCTL::PRTCAPDIR_HOST)
        .set_U2EXIT_LFPS(1)
        .WriteTo(mmio);

    dwc->lock.Release();

    // add a device to bind the XHCI driver
    ZX_DEBUG_ASSERT(dwc->xhci_dev == nullptr);

    zx_device_prop_t props[] = {
        {BIND_PLATFORM_DEV_VID, 0, PDEV_VID_GENERIC},
        {BIND_PLATFORM_DEV_PID, 0, PDEV_PID_GENERIC},
        {BIND_PLATFORM_DEV_DID, 0, PDEV_DID_USB_XHCI},
    };

    device_add_args_t args = {};
    args.version = DEVICE_ADD_ARGS_VERSION;
    args.name = "dwc3";
    args.proto_id = ZX_PROTOCOL_PDEV;
    args.ctx = dwc;
    args.ops = &xhci_device_ops;
    args.props = props;
    args.prop_count = countof(props);

    zx_status_t status = device_add(dwc->parent, &args, &dwc->xhci_dev);
    if (status != ZX_OK) {
        zxlogf(ERROR, "dwc3_start_host_mode failed to add device for XHCI: %d\n", status);
    }
}

void dwc3_usb_reset(dwc3_t* dwc) {
    zxlogf(INFO, "dwc3_usb_reset\n");

    dwc3_ep0_reset(dwc);

    for (unsigned i = 2; i < countof(dwc->eps); i++) {
        dwc3_ep_end_transfers(dwc, i, ZX_ERR_IO_NOT_PRESENT);
        dwc3_ep_set_stall(dwc, i, false);
    }

    dwc3_set_address(dwc, 0);
    dwc3_ep0_start(dwc);
    usb_dci_interface_set_connected(&dwc->dci_intf, true);
}

void dwc3_disconnected(dwc3_t* dwc) {
    zxlogf(INFO, "dwc3_disconnected\n");

    dwc3_cmd_ep_end_transfer(dwc, EP0_OUT);
    dwc->ep0_state = EP0_STATE_NONE;

    if (dwc->dci_intf.ops) {
        usb_dci_interface_set_connected(&dwc->dci_intf, false);
    }

    for (unsigned i = 2; i < countof(dwc->eps); i++) {
        dwc3_ep_end_transfers(dwc, i, ZX_ERR_IO_NOT_PRESENT);
        dwc3_ep_set_stall(dwc, i, false);
    }
}

void dwc3_connection_done(dwc3_t* dwc) {
    auto* mmio = dwc3_mmio(dwc);

    dwc->lock.Acquire();

    uint32_t speed = DSTS::Get().ReadFrom(mmio).CONNECTSPD();
    uint16_t ep0_max_packet = 0;

    switch (speed) {
    case DSTS::CONNECTSPD_HIGH:
        dwc->speed = USB_SPEED_HIGH;
        ep0_max_packet = 64;
        break;
    case DSTS::CONNECTSPD_FULL:
        dwc->speed = USB_SPEED_FULL;
        ep0_max_packet = 64;
        break;
    case DSTS::CONNECTSPD_SUPER:
    case DSTS::CONNECTSPD_ENHANCED_SUPER:
        dwc->speed = USB_SPEED_SUPER;
        ep0_max_packet = 512;
        break;
    default:
        zxlogf(ERROR, "dwc3_connection_done: unsupported speed %u\n", speed);
        dwc->speed = USB_SPEED_UNDEFINED;
        break;
    }

    dwc->lock.Release();

    if (ep0_max_packet) {
        dwc->eps[EP0_OUT].max_packet_size = ep0_max_packet;
        dwc->eps[EP0_IN].max_packet_size = ep0_max_packet;
        dwc3_cmd_ep_set_config(dwc, EP0_OUT, USB_ENDPOINT_CONTROL, ep0_max_packet, 0, true);
        dwc3_cmd_ep_set_config(dwc, EP0_IN, USB_ENDPOINT_CONTROL, ep0_max_packet, 0, true);
    }

    usb_dci_interface_set_speed(&dwc->dci_intf, dwc->speed);
}

void dwc3_set_address(dwc3_t* dwc, unsigned address) {
    auto* mmio = dwc3_mmio(dwc);
    fbl::AutoLock lock(&dwc->lock);

    DCFG::Get().ReadFrom(mmio).set_DEVADDR(address).WriteTo(mmio);
}

void dwc3_reset_configuration(dwc3_t* dwc) {
    auto* mmio = dwc3_mmio(dwc);

    dwc->lock.Acquire();

    // disable all endpoints except EP0_OUT and EP0_IN
    DALEPENA::Get().FromValue(0).EnableEp(EP0_OUT).EnableEp(EP0_IN).WriteTo(mmio);

    dwc->lock.Release();

    for (unsigned i = 2; i < countof(dwc->eps); i++) {
        dwc3_ep_end_transfers(dwc, i, ZX_ERR_IO_NOT_PRESENT);
        dwc3_ep_set_stall(dwc, i, false);
    }
}

static void dwc3_request_queue(void* ctx, usb_request_t* req, const usb_request_complete_t* cb) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    auto* req_int = USB_REQ_TO_INTERNAL(req);
    req_int->complete_cb = *cb;

    zxlogf(LTRACE, "dwc3_request_queue ep: %u\n", req->header.ep_address);
    unsigned ep_num = dwc3_ep_num(req->header.ep_address);
    if (ep_num < 2 || ep_num >= countof(dwc->eps)) {
        zxlogf(ERROR, "dwc3_request_queue: bad ep address 0x%02X\n", req->header.ep_address);
        usb_request_complete_new(req, ZX_ERR_INVALID_ARGS, 0, cb);
        return;
    }

    dwc3_ep_queue(dwc, ep_num, req);
}

static zx_status_t dwc3_set_interface(void* ctx, const usb_dci_interface_t* dci_intf) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    memcpy(&dwc->dci_intf, dci_intf, sizeof(dwc->dci_intf));
    return ZX_OK;
}

static zx_status_t dwc3_config_ep(void* ctx, const usb_endpoint_descriptor_t* ep_desc,
                                  const usb_ss_ep_comp_descriptor_t* ss_comp_desc) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    return dwc3_ep_config(dwc, ep_desc, ss_comp_desc);
}

static zx_status_t dwc3_disable_ep(void* ctx, uint8_t ep_addr) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    return dwc3_ep_disable(dwc, ep_addr);
}

static zx_status_t dwc3_set_stall(void* ctx, uint8_t ep_address) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    return dwc3_ep_set_stall(dwc, dwc3_ep_num(ep_address), true);
}

static zx_status_t dwc3_clear_stall(void* ctx, uint8_t ep_address) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    return dwc3_ep_set_stall(dwc, dwc3_ep_num(ep_address), false);
}

static size_t dwc3_get_request_size(void* ctx) {
    //Allocate dwc_usb_req_internal_t after usb_request_t, to accommodate queueing in
    //the dwc3 layer.
    return sizeof(usb_request_t) + sizeof(dwc_usb_req_internal_t);
}

usb_dci_protocol_ops_t dwc_dci_ops = {
    .request_queue = dwc3_request_queue,
    .set_interface = dwc3_set_interface,
    .config_ep = dwc3_config_ep,
    .disable_ep = dwc3_disable_ep,
    .ep_set_stall = dwc3_set_stall,
    .ep_clear_stall = dwc3_clear_stall,
    .get_request_size = dwc3_get_request_size,
};

static zx_status_t dwc3_set_mode(void* ctx, usb_mode_t mode) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    zx_status_t status = ZX_OK;

    if (mode == USB_MODE_OTG) {
        return ZX_ERR_NOT_SUPPORTED;
    }

    fbl::AutoLock lock(&dwc->usb_mode_lock);

    if (dwc->usb_mode == mode) {
        return ZX_OK;
    }

    // Shutdown if we are in peripheral mode
    if (dwc->usb_mode == USB_MODE_PERIPHERAL) {
        dwc3_events_stop(dwc);
        dwc->irq_handle.reset();
        dwc3_disconnected(dwc);
        dwc3_stop(dwc);
    } else if (dwc->usb_mode == USB_MODE_HOST) {
        if (dwc->xhci_dev) {
            device_remove(dwc->xhci_dev);
            dwc->xhci_dev = nullptr;

            if (mode == USB_MODE_PERIPHERAL) {
                dwc->start_device_on_xhci_release = true;
                return ZX_OK;
            }
        }
    }

    dwc->start_device_on_xhci_release = false;
    if (dwc->ums.ops != nullptr) {
        status = usb_mode_switch_set_mode(&dwc->ums, mode);
        if (status != ZX_OK) {
            goto fail;
        }
    }

    if (mode == USB_MODE_PERIPHERAL) {
        status = pdev_map_interrupt(&dwc->pdev, IRQ_USB3, dwc->irq_handle.reset_and_get_address());
        if (status != ZX_OK) {
            zxlogf(ERROR, "dwc3_set_mode: pdev_map_interrupt failed\n");
            goto fail;
        }

        dwc3_start_peripheral_mode(dwc);
    } else if (mode == USB_MODE_HOST) {
        dwc3_start_host_mode(dwc);
    }

    dwc->usb_mode = mode;
    return ZX_OK;

fail:
    if (dwc->ums.ops != nullptr) {
        usb_mode_switch_set_mode(&dwc->ums, USB_MODE_NONE);
    }
    dwc->usb_mode = USB_MODE_NONE;

    return status;
}

usb_mode_switch_protocol_ops_t dwc_ums_ops = {
    .set_mode = dwc3_set_mode,
};

static void dwc3_unbind(void* ctx) {
    auto* dwc = static_cast<dwc3_t*>(ctx);
    dwc->irq_handle.destroy();
    thrd_join(dwc->irq_thread, nullptr);
    device_remove(dwc->zxdev);
}

static zx_status_t dwc3_get_protocol(void* ctx, uint32_t proto_id, void* out) {
    switch (proto_id) {
    case ZX_PROTOCOL_USB_DCI: {
        auto proto = static_cast<usb_dci_protocol_t*>(out);
        proto->ops = &dwc_dci_ops;
        proto->ctx = ctx;
        return ZX_OK;
    }
    case ZX_PROTOCOL_USB_MODE_SWITCH: {
        auto proto = static_cast<usb_mode_switch_protocol_t*>(out);
        proto->ops = &dwc_ums_ops;
        proto->ctx = ctx;
        return ZX_OK;
    }
    default:
        return ZX_ERR_NOT_SUPPORTED;
    }
}

static void dwc3_release(void* ctx) {
    auto* dwc = static_cast<dwc3_t*>(ctx);

    for (unsigned i = 0; i < countof(dwc->eps); i++) {
        dwc3_ep_fifo_release(dwc, i);
    }
    io_buffer_release(&dwc->event_buffer);
    io_buffer_release(&dwc->ep0_buffer);
    delete dwc;
}

static zx_protocol_device_t dwc3_device_ops = []() {
    zx_protocol_device_t device;
    device.version = DEVICE_OPS_VERSION;
    device.get_protocol = dwc3_get_protocol;
    device.release = dwc3_release;
    return device;
}();

zx_status_t dwc3_bind(void* ctx, zx_device_t* parent) {
    zxlogf(INFO, "dwc3_bind\n");

    auto* dwc = new dwc3_t;
    if (!dwc) {
        return ZX_ERR_NO_MEMORY;
    }

    zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PDEV, &dwc->pdev);
    if (status != ZX_OK) {
        goto fail;
    }

    // USB mode switch is optional, so ignore errors here.
    status = device_get_protocol(parent, ZX_PROTOCOL_USB_MODE_SWITCH, &dwc->ums);
    if (status != ZX_OK) {
        dwc->ums.ops = nullptr;
    }

    status = pdev_get_bti(&dwc->pdev, 0, dwc->bti_handle.reset_and_get_address());
    if (status != ZX_OK) {
        goto fail;
    }

    for (uint8_t i = 0; i < countof(dwc->eps); i++) {
        dwc3_endpoint_t* ep = &dwc->eps[i];
        ep->ep_num = i;
        list_initialize(&ep->queued_reqs);
    }
    dwc->parent = parent;
    dwc->usb_mode = USB_MODE_NONE;

    mmio_buffer_t mmio;
    status = pdev_map_mmio_buffer2(&dwc->pdev, MMIO_USB3OTG, ZX_CACHE_POLICY_UNCACHED_DEVICE,
                                   &mmio);
    if (status != ZX_OK) {
        zxlogf(ERROR, "dwc3_bind: pdev_map_mmio_buffer failed\n");
        goto fail;
    }
    dwc->mmio = ddk::MmioBuffer(mmio);

    status = io_buffer_init(&dwc->event_buffer, dwc->bti_handle.get(), EVENT_BUFFER_SIZE,
                            IO_BUFFER_RO | IO_BUFFER_CONTIG);
    if (status != ZX_OK) {
        zxlogf(ERROR, "dwc3_bind: io_buffer_init failed\n");
        goto fail;
    }
    io_buffer_cache_flush(&dwc->event_buffer, 0, EVENT_BUFFER_SIZE);

    status = io_buffer_init(&dwc->ep0_buffer,  dwc->bti_handle.get(), UINT16_MAX,
                            IO_BUFFER_RW | IO_BUFFER_CONTIG);
    if (status != ZX_OK) {
        zxlogf(ERROR, "dwc3_bind: io_buffer_init failed\n");
        goto fail;
    }

    status = dwc3_ep0_init(dwc);
    if (status != ZX_OK) {
        zxlogf(ERROR, "dwc3_bind: dwc3_ep_init failed\n");
        goto fail;
    }

{
    device_add_args_t args = {};
    args.version = DEVICE_ADD_ARGS_VERSION;
    args.name = "dwc3";
    args.ctx = dwc;
    args.ops = &dwc3_device_ops;
    args.proto_id = ZX_PROTOCOL_USB_DCI;
    args.proto_ops = &dwc_dci_ops,

    status = device_add(parent, &args, &dwc->zxdev);
    if (status != ZX_OK) {
        goto fail;
    }
}

    return ZX_OK;

fail:
    zxlogf(ERROR, "dwc3_bind failed %d\n", status);
    dwc3_release(dwc);
    return status;
}

static zx_driver_ops_t dwc3_driver_ops = [](){
    zx_driver_ops_t ops;
    ops.version = DRIVER_OPS_VERSION;
    ops.bind = dwc3_bind;
    return ops;
}();

// clang-format off
ZIRCON_DRIVER_BEGIN(dwc3, dwc3_driver_ops, "zircon", "0.1", 3)
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_VID, PDEV_VID_GENERIC),
    BI_ABORT_IF(NE, BIND_PLATFORM_DEV_PID, PDEV_PID_GENERIC),
    BI_MATCH_IF(EQ, BIND_PLATFORM_DEV_DID, PDEV_DID_USB_DWC3),
ZIRCON_DRIVER_END(dwc3)
// clang-format on
