⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 otg_fsm.c

📁 philips公司ISP1362 USB OTG控制芯片的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*************************************************************
 * Philips OTG FSM module for USB OTG controller
 *
 * (c) 2002 Koninklijke Philips Electronics N.V., All rights reserved
 * 
 * This  source code and any compilation or derivative thereof is the
 * proprietary information of Koninklijke Philips Electronics N.V.
 * and is confidential in nature.
 * Under no circumstances is this software to be exposed to or placed
 * under an Open Source License of any type without the expressed
 * written permission of Koninklijke Philips Electronics N.V.
 *
 * File Name:	otg_fsm.c
 *
 * History:	
 *
 *	Version	Date		Author		Comments
 * -------------------------------------------------
 * 	1.0		09/23/02	SYARRA		Initial Creation
 *	1.10	04/01/03	SYARRA		OTG1.0A fixes
 *	1.21	08/04/03	SYARRA		OPT1.2 compliance
 *************************************************************/


#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/ioport.h>
#include <linux/sched.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/smp_lock.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/interrupt.h>  /* for in_interrupt() */
#undef DEBUG
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
#include <asm/unaligned.h>

#include <linux/usb.h>

#include "pdc_intf.h"
#include "usb_phci.h"
#include "usb_otg.h"

#define		HC_IO_BASE						0x290
#define		HC_DATA							HC_IO_BASE
#define		HC_COM							(HC_IO_BASE+2)

__u32	otg_fn;

char	fsm_state_X_name[25][15] = {
		"B_IDLE",
		"B_HOST",
		"B_PERIPHERAL",
		"B_WAIT_ACON",
		"B_SRP_INIT",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"INV_STATE",
		"A_IDLE",
		"A_HOST",
		"A_PERIPHERAL",
		"A_WAIT_BCON",
		"A_WAIT_VRISE",
		"A_SUSPEND",
		"A_WAIT_VFALL",
		"A_VBUS_ERR"
};

struct isp1362_dev	*isp1362_otg_dev = NULL;

unsigned char	fsm_state_X_app_state[25] = {
		B_IDLE,
		B_HOST,
		B_PERIPHERAL,
		B_PERIPHERAL,
		B_IDLE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		INV_STATE,
		A_IDLE,
		A_HOST,
		A_PERIPHERAL,
		A_IDLE,
		A_IDLE,
		A_HOST,
		A_IDLE,
		A_VBUS_ERR
};

#ifdef CONFIG_DETAIL_DEBUG
/*----------------------------------------------*/
/* printing function declerations				*/
/* ---------------------------------------------*/
void otgfsm_print_otg_data(otg_fsm_t	*fsm_data);
void otgfsm_print_status(otg_fsm_t		*fsm_data);
#endif /* CONFIG_DETAIL_DEBUG */

/*----------------------------------------------*/
/* control register function declerations		*/
/* ---------------------------------------------*/
void otgfsm_local_pulldown(__u8 ctrl_flag);
void otgfsm_local_pullup(__u8 ctrl_flag) ;
void otgfsm_local_vbus(otg_fsm_t	*fsm_data, __u8 ctrl_flag);
void otgfsm_hc_dc_sel(__u8 ctrl_flag);
void otgfsm_srp_det_en(__u8 ctrl_flag) ;
void otgfsm_rdis_lcon_en(__u8 ctrl_flag);
void otgfsm_rcon_lse0_en(__u8 ctrl_flag);

/*----------------------------------------------*/
/*	timer related functions						*/
/* ---------------------------------------------*/
void otgfsm_start_timer(otg_fsm_t	*fsm_data, __u8	timer_id, __u16	time );
void otgfsm_stop_timer(otg_fsm_t	*fsm_data);

void otgfsm_status_probe(otg_fsm_t	*fsm_data);

void otgfsm_run_Adevice(otg_fsm_t	*fsm_data);
void otgfsm_run_Bdevice(otg_fsm_t	*fsm_data);
void otgfsm_run(otg_fsm_t	*fsm_data);

void otgfsm_init(otg_fsm_t	*fsm_data );
void otgfsm_init_fsm_data(otg_fsm_t	*fsm_data);

void otgfsm_set_state(otg_fsm_t	*fsm_data, __u8	cmd);

/* ISP1362 Hardware register access functions */

static	void	otg_reg_read16(__u16 reg, __u16	*data)
{
	isp1362_reg_read16(isp1362_otg_dev, reg, (*data));
}

static	void	otg_reg_write16(__u16 reg, __u32 data)
{
	isp1362_reg_write16(isp1362_otg_dev, (reg|0x80), data);
}

static	void	otg_reg_read32(__u16 reg, __u32 *data)
{
	isp1362_reg_read32(isp1362_otg_dev, reg, (*data));

	return;
}

static	void	otg_reg_write32(__u16 reg, __u32 data)
{
	isp1362_reg_write32(isp1362_otg_dev, (reg|0x80), data);

	return;
}




#ifdef CONFIG_DETAIL_DEBUG
/*----------------------------------------------*/
/* Print OTG status registers					*/
/* ---------------------------------------------*/
void otgfsm_print_status(otg_fsm_t		*fsm_data) {
	__u16	status;
	__u16	interrupt;

	interrupt = fsm_data->regs.int_port.data;
	status = fsm_data->regs.status_port.data;

	detail_debug(("Printing Status Change: in [%s]\n", (fsm_data->tcb.state != INV_STATE ) ? fsm_state_X_name[fsm_data->tcb.state] : "INV_STATE"));

	if(interrupt & OTG_IRQ_ID) {
		detail_debug(("  ID[%d]", status & OTG_IRQ_ID));
	}
	if(interrupt & OTG_IRQ_A_VBUS_VLD) {
		detail_debug(("  A_VbusVld[%d]", (status & OTG_IRQ_A_VBUS_VLD)?1:0));
	}
	if(interrupt & OTG_IRQ_B_SESS_END) {
		detail_debug(("  B_SessEnd[%d]", (status & OTG_IRQ_B_SESS_END)?1:0));
	}
	if(interrupt & OTG_IRQ_A_SESS_VLD) {
		detail_debug(("  A_SessVld[%d]", (status & OTG_IRQ_A_SESS_VLD)?1:0));
	}
	if(interrupt & OTG_IRQ_B_SESS_VLD) {
		detail_debug(("  B_SessVld[%d]", (status & OTG_IRQ_B_SESS_VLD)?1:0));
	}
	if(interrupt & OTG_IRQ_RMT_CONN) {
		detail_debug(("  Conn[%d]", (status & OTG_IRQ_RMT_CONN)?1:0));
	}
	if(interrupt & OTG_IRQ_SUSPEND) {
		detail_debug(("  Susp[1]"));
	}
	if(interrupt & OTG_IRQ_RESUME) {
		detail_debug(("  Res[1]"));
	}
	if(interrupt & OTG_IRQ_SRP_DET) {
		detail_debug(("  Srp[1]"));
	}
	if(interrupt & OTG_IRQ_SE0_SRP){
		detail_debug(("  Srp[1]"));
	}
	if(interrupt & OTG_IRQ_TMR) {
		detail_debug(("  Tmr[1]"));
	}
	detail_debug(("\n"))
}

/*----------------------------------------------*/
/* Print OTG fsm data							*/
/* ---------------------------------------------*/
void otgfsm_print_otg_data(otg_fsm_t	*fsm_data){

	__u16	wTemp;
	otg_tcb_t	*tcb = &(fsm_data->tcb);


	detail_debug(("printing OTG FSM Data\n"))
	detail_debug(("TCB::\n"))
	detail_debug(("     state = %d err_code = %d id = %d\n", tcb->state, tcb->err_code, tcb->id))
	detail_debug(("     for A-device::\n          a_vbus_vld = %d a_sess_vld = %d a_srp_det = %d b_conn = %d b_bus_suspend = %d b_bus_resume = %d\n", tcb->a_vbus_vld, tcb->a_sess_vld, tcb->a_srp_det, tcb->b_conn, tcb->b_bus_suspend, tcb->b_bus_resume))

   	detail_debug(("          b_hnp_support = %d b_srp_support = %d a_set_b_hnp_en = %d a_suspend_req = %d \n", tcb->b_hnp_support, tcb->b_srp_support, tcb->a_set_b_hnp_en, tcb->a_suspend_req))

	detail_debug(("     for B-device:: \n          b_sess_end = %d b_sess_vld = %d b_se0_srp = %d a_conn = %d a_bus_suspend = %d a_bus_resume = %d \n", tcb->b_sess_end, tcb->b_sess_vld, tcb->b_se0_srp, tcb->a_conn, tcb->a_bus_suspend, tcb->a_bus_resume))
	detail_debug(("          a_bus_reset = %d b_srp_done = %d b_hnp_en = %d a_hnp_support = %d a_alt_hnp_support = %d \n", tcb->a_bus_reset, tcb->b_srp_done, tcb->b_hnp_en, tcb->a_hnp_support, tcb->a_alt_hnp_support))
	detail_debug(("     for both A-device and B-device::\n          bus_req = %d bus_drop = %d Req4StateChange = %d TimeOut =%d TimerRunning = %d TimerID = %d TimerTick = %d\n", tcb->bus_req, tcb->bus_drop, tcb->Req4StateChange, tcb->TimeOut, tcb->TimerRunning, tcb->TimerId, tcb->TimerTick))

	otg_reg_read16(OTG_CONTROL_REG, &wTemp);
	detail_debug(("     Control Reg = %x\n", wTemp))
	otg_reg_read16(OTG_STATUS_REG, &wTemp);
	detail_debug(("     Status Reg = %x\n", wTemp&0x3F))
	otg_reg_read16(OTG_INT_REG, &wTemp);
	detail_debug(("     Interrupt Reg = %x\n", wTemp & OTG_IRQ_MASK))
	otg_reg_read16(OTG_INT_ENABLE_REG, &wTemp);
	detail_debug(("     Interrrupt Enable Reg = %x\n", wTemp&OTG_IRQ_MASK))
	otg_reg_read16(OTG_TMR_REG, &wTemp);
	detail_debug(("     Timer Reg = %x\n\n", wTemp))
}
#endif /* CONFIG_DETAIL_DEBUG */

/*----------------------------------------------*/
/* control local pulldown register on D- line	*/
/* ---------------------------------------------*/
void otgfsm_local_pulldown(__u8 ctrl_flag) {
	__u16	wTemp;

	if(ctrl_flag == TRUE )	{

		//pulldown on D- is always enabled 
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_LOC_PULLDN_DM));

	} else {

		//pulldown on D- is disabled
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, wTemp&(~OTG_LOC_PULLDN_DM));
	}
}

/*----------------------------------------------*/
/* control local pulldown resister on D+ line	*/
/* ---------------------------------------------*/
void otgfsm_local_pullup(__u8 ctrl_flag) {
	__u16	wTemp;

	//for FPGA testing, ISP1181 chip needs SoftConnect bit and Vbus sensing to check suspend/awake
	if( ctrl_flag == TRUE )	{

		//pulldown on D+ is disabled when pullup enabled
		
		pdc_otg_control(NULL, PDC_CONNECT);
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		wTemp &= (~OTG_LOC_PULLDN_DP);
		wTemp &= (~OTG_A_RDIS_LCON_EN);
		wTemp |= OTG_LOC_CONN;
		//disable auto connect (a_rdis_lcon_en bit)
		otg_reg_write16(OTG_CONTROL_REG, wTemp);
	} else {
		   	//pulldown on D+ is enabled when pullup disabled
		pdc_otg_control(NULL, PDC_DISCONNECT);
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		wTemp &= ~(OTG_LOC_CONN);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_LOC_PULLDN_DP));
	}
}

/*----------------------------------------------*/
/* Select HC or DC for the OTG port				*/
/* control SEL_HC_DC. 0: HC, 1: DC				*/
/* ---------------------------------------------*/
void otgfsm_hc_dc_sel(__u8 ctrl_flag) {

	__u16	wTemp;

	if( ctrl_flag == TRUE ) {

		// Select DC
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_SEL_HC_DC));

	} else {

		// selct HC
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp&(~OTG_SEL_HC_DC)));
	}
}

/*----------------------------------------------*/
/* Enable/disable SRP detection for OTG port 	*/
/* VBUS pulsing SRP detection is used if enbaled*/
/* ---------------------------------------------*/
void otgfsm_srp_det_en(__u8 ctrl_flag) {

	__u16	wTemp;

	if( ctrl_flag == TRUE ) {

		// Enable SRP (VBUS Pulsing) detection 
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);

		//VBUS pulsing(use a_sess_vld)
		//Dataline pulsing(use D+ or D- low to high)
		wTemp |= OTG_A_SRP_DET_EN;
	   	wTemp &= (~OTG_A_SEL_SRP);
		otg_reg_write16(OTG_CONTROL_REG, wTemp);

	} else {

		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, wTemp&(~OTG_A_SRP_DET_EN));

	}
}

/*----------------------------------------------*/
/* Enable/disable Local connect 				*/
/* ---------------------------------------------*/
void otgfsm_rdis_lcon_en(__u8 ctrl_flag) {

	__u16	wTemp;

	if(ctrl_flag == TRUE) {

		// Enable local connection
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_A_RDIS_LCON_EN));

	} else {

		// Disable local connection
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp&(~OTG_A_RDIS_LCON_EN)));

	}
}

void otgfsm_rcon_lse0_en(__u8 ctrl_flag) {
	__u16   wTemp;

	if(ctrl_flag == TRUE) {
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp|OTG_B_RCON_LSE0_EN));
	} else {
		otg_reg_read16(OTG_CONTROL_REG, &wTemp);
		otg_reg_write16(OTG_CONTROL_REG, (wTemp&(~OTG_B_RCON_LSE0_EN)));
	}
}

void otgfsm_print_fn(otg_fsm_t	*fsm_data, char *mesg)
{
	__u32	fn, fn_rem;

	otg_reg_read32(HC_FN_REG, &fn);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -