/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2014 Rockchip Electronics
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */


#include <usb/usb.h>
#include "generic_hub.h"
#include "dwc2_private.h"
#include "dwc2.h"

static int
dwc2_rh_port_status_changed(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	int changed;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	changed = hprt.prtconndet;

	/* Clear connect detect flag */
	if (changed) {
		hprt.d32 &= HPRT_W1C_MASK;
		hprt.prtconndet = 1;
		writel(hprt.d32, dwc2->hprt0);
	}
	return changed;
}

static int
dwc2_rh_port_connected(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	return hprt.prtconnsts;
}

static int
dwc2_rh_port_in_reset(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	return hprt.prtrst;
}

static int
dwc2_rh_port_enabled(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	return hprt.prtena;
}

static usb_speed
dwc2_rh_port_speed(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	if (hprt.prtena) {
		switch (hprt.prtspd) {
		case PRTSPD_HIGH:
			return HIGH_SPEED;
		case PRTSPD_FULL:
			return FULL_SPEED;
		case PRTSPD_LOW:
			return LOW_SPEED;
		}
	}
	return -1;
}

static int
dwc2_rh_reset_port(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	hprt.d32 &= HPRT_W1C_MASK;
	hprt.prtrst = 1;
	writel(hprt.d32, dwc2->hprt0);

	/* Wait a bit while reset is active. */
	mdelay(50);

	/* Deassert reset. */
	hprt.prtrst = 0;
	writel(hprt.d32, dwc2->hprt0);

	/*
	 * If reset and speed enum success the DWC2 core will set enable bit
	 * after port reset bit is deasserted
	 */
	mdelay(1);
	hprt.d32 = readl(dwc2->hprt0);
	usb_debug("%s reset port ok, hprt = 0x%08x\n", __func__, hprt.d32);

	if (!hprt.prtena) {
		usb_debug("%s enable port fail! hprt = 0x%08x\n",
			  __func__, hprt.d32);
		return -1;
	}

	return 0;
}

static int
dwc2_rh_enable_port(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	/* Power on the port */
	hprt.d32 = readl(dwc2->hprt0);
	hprt.d32 &= HPRT_W1C_MASK;
	hprt.prtpwr = 1;
	writel(hprt.d32, dwc2->hprt0);
	return 0;
}

static int
dwc2_rh_disable_port(usbdev_t *const dev, const int port)
{
	hprt_t hprt;
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

	hprt.d32 = readl(dwc2->hprt0);
	hprt.d32 &= HPRT_W1C_MASK;
	/* Disable the port*/
	hprt.prtena = 1;
	/* Power off the port */
	hprt.prtpwr = 0;
	writel(hprt.d32, dwc2->hprt0);
	return 0;
}

static const generic_hub_ops_t dwc2_rh_ops = {
	.hub_status_changed	= NULL,
	.port_status_changed	= dwc2_rh_port_status_changed,
	.port_connected		= dwc2_rh_port_connected,
	.port_in_reset		= dwc2_rh_port_in_reset,
	.port_enabled		= dwc2_rh_port_enabled,
	.port_speed		= dwc2_rh_port_speed,
	.enable_port		= dwc2_rh_enable_port,
	.disable_port		= dwc2_rh_disable_port,
	.start_port_reset	= NULL,
	.reset_port		= dwc2_rh_reset_port,
};

void
dwc2_rh_init(usbdev_t *dev)
{
	dwc_ctrl_t *const dwc2 = DWC2_INST(dev->controller);

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

	generic_hub_init(dev, 1, &dwc2_rh_ops);
	usb_debug("dwc2_rh_init HPRT 0x%08x p = %p\n ",
		  readl(dwc2->hprt0), dwc2->hprt0);
	usb_debug("DWC2: root hub init done\n");
}
