/*
 * This file is part of the libpayload project.
 *
 * Copyright (C) 2013 secunet Security Networks AG
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

//#define USB_DEBUG

#include <usb/usb.h>
#include "generic_hub.h"
#include "xhci_private.h"
#include "xhci.h"

static int
xhci_rh_hub_status_changed(usbdev_t *const dev)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	const int changed = !!(xhci->opreg->usbsts & USBSTS_PCD);
	if (changed)
		xhci->opreg->usbsts =
			(xhci->opreg->usbsts & USBSTS_PRSRV_MASK) | USBSTS_PCD;
	return changed;
}

static int
xhci_rh_port_status_changed(usbdev_t *const dev, const int port)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc;

	const int changed = !!(*portsc & (PORTSC_CSC | PORTSC_PRC));
	/* always clear all the status change bits */
	*portsc = (*portsc & PORTSC_RW_MASK) | 0x00fe0000;
	return changed;
}

static int
xhci_rh_port_connected(usbdev_t *const dev, const int port)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc;

	return *portsc & PORTSC_CCS;
}

static int
xhci_rh_port_in_reset(usbdev_t *const dev, const int port)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc;

	return !!(*portsc & PORTSC_PR);
}

static int
xhci_rh_port_enabled(usbdev_t *const dev, const int port)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc;

	return !!(*portsc & PORTSC_PED);
}

static usb_speed
xhci_rh_port_speed(usbdev_t *const dev, const int port)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc;

	if (*portsc & PORTSC_PED) {
		return ((*portsc & PORTSC_PORT_SPEED_MASK)
				>> PORTSC_PORT_SPEED_START)
			- 1;
	} else {
		return -1;
	}
}

static int
xhci_rh_reset_port(usbdev_t *const dev, const int port)
{
	xhci_t *const xhci = XHCI_INST(dev->controller);
	volatile u32 *const portsc = &xhci->opreg->prs[port - 1].portsc;

	/* Trigger port reset. */
	*portsc = (*portsc & PORTSC_RW_MASK) | PORTSC_PR;

	/* Wait for port_in_reset == 0, up to 150 * 1000us = 150ms */
	if (generic_hub_wait_for_port(dev, port, 0, xhci_rh_port_in_reset,
				      150, 1000) == 0)
		usb_debug("xhci_rh: Reset timed out at port %d\n", port);
	else
		/* Clear reset status bits, since port is out of reset. */
		*portsc = (*portsc & PORTSC_RW_MASK) | PORTSC_PRC | PORTSC_WRC;

	return 0;
}

static int
xhci_rh_enable_port(usbdev_t *const dev, int port)
{
	if (IS_ENABLED(CONFIG_LP_USB_XHCI_MTK_QUIRK)) {
		xhci_t *const xhci = XHCI_INST(dev->controller);
		volatile u32 *const portsc =
			&xhci->opreg->prs[port - 1].portsc;

		/*
		 * Before sending commands to a port, the Port Power in
		 * PORTSC register should be enabled on MTK's xHCI.
		 */
		*portsc = (*portsc & PORTSC_RW_MASK) | PORTSC_PP;
	}
	return 0;
}


static const generic_hub_ops_t xhci_rh_ops = {
	.hub_status_changed	= xhci_rh_hub_status_changed,
	.port_status_changed	= xhci_rh_port_status_changed,
	.port_connected		= xhci_rh_port_connected,
	.port_in_reset		= xhci_rh_port_in_reset,
	.port_enabled		= xhci_rh_port_enabled,
	.port_speed		= xhci_rh_port_speed,
	.enable_port		= xhci_rh_enable_port,
	.disable_port		= NULL,
	.start_port_reset	= NULL,
	.reset_port		= xhci_rh_reset_port,
};

void
xhci_rh_init (usbdev_t *dev)
{
	/* we can set them here because a root hub _really_ shouldn't
	   appear elsewhere */
	dev->address = 0;
	dev->hub = -1;
	dev->port = -1;

	const int num_ports = /* TODO: maybe we need to read extended caps */
		(XHCI_INST(dev->controller)->capreg->hcsparams1 >> 24) & 0xff;
	generic_hub_init(dev, num_ports, &xhci_rh_ops);

	usb_debug("xHCI: root hub init done\n");
}
