
/*
 * arch/arm/cpu/armv8/gxb/usb.c
 *
 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

//#include <common.h>
//#include <asm/cache.h>
#include <asm/arch/usb.h>
#include <asm/arch/romboot.h>
#include <asm/arch/secure_apb.h>

#ifdef CONFIG_USB_DWC_OTG_HCD
static amlogic_usb_config_t * g_usb_cfg[BOARD_USB_MODE_MAX][USB_PHY_PORT_MAX];

static char * g_clock_src_name_m8[]={
    "XTAL input",
};

extern void _udelay(unsigned long usec);
extern void _mdelay(unsigned long usec);
//static int reset_count = 0;
//int set_usb_phy_clk(struct lm_device * plmdev,int is_enable)
//{
static int set_usb_phy_clock(amlogic_usb_config_t * usb_cfg)
{

	int port_idx;
	usb_peri_reg_t * peri;
	usb_config_data_t config;
	usb_ctrl_data_t control;
	int clk_sel,clk_div;
	unsigned int port = usb_cfg->base_addr & USB_PHY_PORT_MSK;
	int time_dly = 500; //usec

	if (!usb_cfg)
		return -1;


	if (port == USB_PHY_PORT_A) {
		port_idx = 0;
		peri = (usb_peri_reg_t*)PREI_USB_PHY_REG_A;//CBUS_REG_ADDR(PREI_USB_PHY_REG_A);
	}else if(port == USB_PHY_PORT_B){
		port_idx = 1;
		peri = (usb_peri_reg_t*)PREI_USB_PHY_REG_B;//CBUS_REG_ADDR(PREI_USB_PHY_REG_B);
	}else{
		printf("usb base address error: %x\n",usb_cfg->base_addr);
		return -1;
	}
	writel((1 << 2),P_RESET1_REGISTER);
	printf("USB (%d) peri reg base: %x\n",port_idx,(uint32_t)(unsigned long long)peri);
	clk_sel = usb_cfg->clk_selecter;
	clk_div = usb_cfg->pll_divider;

	config.d32 = peri->config;
	config.b.clk_32k_alt_sel= 1;
	peri->config = config.d32;

	printf("USB (%d) use clock source: %s, div: %d\n",port_idx,g_clock_src_name_m8[clk_sel], clk_div);

	control.d32 = peri->ctrl;
	control.b.fsel = 5;	/* PHY default is 24M (5), change to 12M (2) */
	control.b.por = 1;  /* power off default*/
	peri->ctrl = control.d32;
	_udelay(time_dly);
	return 0;
}
//call after set clock
void set_usb_phy_power(amlogic_usb_config_t * usb_cfg,int is_on)
{
	unsigned long delay = 1000;
	int port_idx = 100;
	unsigned int port = usb_cfg->base_addr & USB_PHY_PORT_MSK;
	usb_peri_reg_t *peri_a,*peri_b,*peri_c,*peri_d,*peri;
	peri = NULL;
	usb_ctrl_data_t control;
	usb_adp_bc_data_t adp_bc;

	peri_a = (usb_peri_reg_t*)PREI_USB_PHY_REG_A;//CBUS_REG_ADDR(PREI_USB_PHY_REG_A);
	peri_b = (usb_peri_reg_t*)PREI_USB_PHY_REG_B;//CBUS_REG_ADDR(PREI_USB_PHY_REG_B);
//	peri_c = (usb_peri_reg_t*)CBUS_REG_ADDR(PREI_USB_PHY_REG_C);
//	peri_d = (usb_peri_reg_t*)CBUS_REG_ADDR(PREI_USB_PHY_REG_D);
	peri_c = NULL;
	peri_d = NULL;

	if (port == USB_PHY_PORT_A) {
		peri = peri_a;
		port_idx = 0;
	}else if(port == USB_PHY_PORT_B){
		peri = peri_b;
		port_idx = 1;
	}
	else if(port == USB_PHY_PORT_C){
		peri = peri_c;
		port_idx = 2;
	}else if(port == USB_PHY_PORT_D){
		peri = peri_d;
		port_idx = 3;
	}

	if (is_on) {
		control.d32 = peri->ctrl;
		control.b.por = 0;
		peri->ctrl = control.d32;

		_udelay(delay);
		/* read back clock detected flag*/
		control.d32 = peri->ctrl;
		if (!control.b.clk_detected) {
			printf("USB (%d) PHY Clock not detected!\n",port_idx);
		}
		if (port == USB_PHY_PORT_B) {
			adp_bc.d32 = peri->adp_bc;
			adp_bc.b.aca_enable = 1;
			peri->adp_bc = adp_bc.d32;
			_udelay(50);
			adp_bc.d32 = peri->adp_bc;
			if (adp_bc.b.aca_pin_float) {
				printf("USB-B ID detect failed!\n");
				printf("Please use the chip after version RevA1!\n");
				return;
			}
		}
	}else{
		control.d32 = peri->ctrl;
		control.b.por = 1;
		peri->ctrl = control.d32;
	}
	_udelay(delay);

}
const char * bc_name[]={
	"UNKNOWN",
	"SDP (PC)",
	"DCP (Charger)",
	"CDP (PC with Charger)",
};
#define T_DCD_TIMEOUT	10
#define T_VDPSRC_ON	40
#define T_VDMSRC_EN	(20 + 5)
#define T_VDMSRC_DIS	(20 + 5)
#define T_VDMSRC_ON	40
static void usb_bc_detect(amlogic_usb_config_t * usb_cfg)
{
	int port_idx,timeout_det;
	unsigned int port = usb_cfg->base_addr & USB_PHY_PORT_MSK;
	usb_peri_reg_t *peri,*peri_a,*peri_b,*peri_c,*peri_d;
	peri = NULL;
	port_idx = 100;
	usb_adp_bc_data_t adp_bc;
	int bc_mode = BC_MODE_UNKNOWN;

	peri_a = (usb_peri_reg_t*)PREI_USB_PHY_REG_A;//CBUS_REG_ADDR(PREI_USB_PHY_REG_A);
	peri_b = (usb_peri_reg_t*)PREI_USB_PHY_REG_B;//CBUS_REG_ADDR(PREI_USB_PHY_REG_B);
//	peri_c = (usb_peri_reg_t*)CBUS_REG_ADDR(PREI_USB_PHY_REG_C);
//	peri_d = (usb_peri_reg_t*)CBUS_REG_ADDR(PREI_USB_PHY_REG_D);
	peri_c = NULL;
	peri_d = NULL;

	if (port == USB_PHY_PORT_A) {
		peri = peri_a;
		port_idx = 0;
	}else if(port == USB_PHY_PORT_B){
		peri = peri_b;
		port_idx = 1;
	}
	else if(port == USB_PHY_PORT_C){
		peri = peri_c;
		port_idx = 2;
	}else if(port == USB_PHY_PORT_D){
		peri = peri_d;
		port_idx = 3;
	}

	adp_bc.d32 = peri->adp_bc;
	if (adp_bc.b.device_sess_vld) {
		_mdelay(T_DCD_TIMEOUT);

		/* Turn on VDPSRC */
		adp_bc.b.chrgsel = 0;
		adp_bc.b.vdatdetenb = 1;
		adp_bc.b.vdatsrcenb = 1;
		adp_bc.b.dcd_enable = 0;
		peri->adp_bc = adp_bc.d32;

		/* SDP and CDP/DCP distinguish */
		timeout_det = T_VDMSRC_EN;
		while (timeout_det--) {
			adp_bc.d32 = peri->adp_bc;
			if (adp_bc.b.chg_det)
				break;
			_mdelay(1);
		};

		if (adp_bc.b.chg_det) {
			/* Turn off VDPSRC */
			adp_bc.d32 = peri->adp_bc;
			adp_bc.b.vdatdetenb = 0;
			adp_bc.b.vdatsrcenb = 0;
			peri->adp_bc = adp_bc.d32;

			/* Wait VDMSRC_DIS */
			timeout_det = T_VDMSRC_DIS;
			while (timeout_det--) {
				adp_bc.d32 = peri->adp_bc;
				if (!adp_bc.b.chg_det)
					break;
				_mdelay(1);
			};

			if (timeout_det <= 0)
				printf("Time out for VDMSRC_DIS!");

			/* Turn on VDMSRC */
			adp_bc.d32 = peri->adp_bc;
			adp_bc.b.chrgsel = 1;
			adp_bc.b.vdatdetenb = 1;
			adp_bc.b.vdatsrcenb = 1;
			peri->adp_bc = adp_bc.d32;

			_mdelay(T_VDMSRC_ON);
			adp_bc.d32 = peri->adp_bc;
			if (adp_bc.b.chg_det)
				bc_mode = BC_MODE_DCP;
			else
				bc_mode = BC_MODE_CDP;
		}
		else{
			bc_mode = BC_MODE_SDP;
		}
		adp_bc.d32 = peri->adp_bc;
		adp_bc.b.vdatdetenb = 0;
		adp_bc.b.vdatsrcenb = 0;
		adp_bc.b.dcd_enable = 0;
		peri->adp_bc = adp_bc.d32;
	}

	printf("Port %d detect usb battery charger mode: %s\n",port_idx, bc_name[bc_mode]);
	usb_cfg->battery_charging_det_cb(bc_mode);

}
amlogic_usb_config_t * board_usb_start(int mode,int index)
{
	if (mode < 0 || mode >= BOARD_USB_MODE_MAX||!g_usb_cfg[mode][index])
		return 0;


	set_usb_phy_clock(g_usb_cfg[mode][index]);
	set_usb_phy_power(g_usb_cfg[mode][index],1);//on
	if(mode == BOARD_USB_MODE_CHARGER &&
	    g_usb_cfg[mode][index]->battery_charging_det_cb)
		usb_bc_detect(g_usb_cfg[mode][index]);
	return g_usb_cfg[mode][index];
}

int board_usb_stop(int mode,int index)
{
	printf("board_usb_stop cfg: %d\n",mode);
	if (mode < 0 || mode >= BOARD_USB_MODE_MAX)
		return 1;
	set_usb_phy_power(g_usb_cfg[mode][index],0);//off

	return 0;
}

int usb_index = 0;
void board_usb_init(amlogic_usb_config_t * usb_cfg,int mode)
{

	if (mode < 0 || mode >= BOARD_USB_MODE_MAX || !usb_cfg)
		return ;

	if (mode == BOARD_USB_MODE_HOST) {
		if (usb_index >= USB_PHY_PORT_MAX)
			return;
		g_usb_cfg[mode][usb_index] = usb_cfg;
		usb_index++;
	}else
		g_usb_cfg[mode][0] = usb_cfg;
	printf("register usb cfg[%d][%d] = %p\n",mode,(mode==BOARD_USB_MODE_HOST)?usb_index:0,usb_cfg);
}

int get_usb_count(void)
{
    return  usb_index;
}
#endif //CONFIG_USB_DWC_OTG_HCD
