// 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 <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(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
