📄 otg_fsm.c
字号:
/************************************************************* * 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 * *************************************************************/#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)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_command(reg,isp1362_otg_dev); *data = isp1362_read16(isp1362_otg_dev);}static void otg_reg_write16(__u16 reg, __u32 data){ isp1362_command((reg|0x80),isp1362_otg_dev); isp1362_write16(data,isp1362_otg_dev);}#if 0/* Not in USE */static void otg_reg_read32(__u16 reg, __u32 *data){ __u16 w_data; isp1362_command(reg, isp1362_otg_dev); w_data = isp1362_read16(isp1362_otg_dev); *data = w_data & 0x0000FFFF; w_data = isp1362_read16(isp1362_otg_dev); *data |= (w_data & 0x0000FFFF) << 16; return ;}#endifstatic void otg_reg_write32(__u16 reg, __u32 data){ __u16 w_data; isp1362_command((reg|0x80), isp1362_otg_dev); w_data = data & 0x0000FFFF; isp1362_write16(w_data,isp1362_otg_dev); w_data = (data & 0xFFFF0000) >> 16; isp1362_write16(w_data,isp1362_otg_dev); 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(REG_OTG_CONTROL, &wTemp); detail_debug((" Control Reg = %x\n", wTemp)) otg_reg_read16(REG_OTG_STATUS, &wTemp); detail_debug((" Status Reg = %x\n", wTemp&0x3F)) otg_reg_read16(REG_OTG_INT, &wTemp); detail_debug((" Interrupt Reg = %x\n", wTemp & OTG_IRQ_MASK)) otg_reg_read16(REG_OTG_INT_ENABLE, &wTemp); detail_debug((" Interrrupt Enable Reg = %x\n", wTemp&OTG_IRQ_MASK)) otg_reg_read16(REG_OTG_TMR, &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(REG_OTG_CONTROL, &wTemp); otg_reg_write16(REG_OTG_CONTROL, (wTemp|OTG_LOC_PULLDN_DM)); } else { //pulldown on D- is disabled otg_reg_read16(REG_OTG_CONTROL, &wTemp); otg_reg_write16(REG_OTG_CONTROL, 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(REG_OTG_CONTROL, &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(REG_OTG_CONTROL, wTemp); } else { //pulldown on D+ is enabled when pullup disabled pdc_otg_control(NULL, PDC_DISCONNECT); otg_reg_read16(REG_OTG_CONTROL, &wTemp); wTemp &= ~(OTG_LOC_CONN); otg_reg_write16(REG_OTG_CONTROL, (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(REG_OTG_CONTROL, &wTemp); otg_reg_write16(REG_OTG_CONTROL, (wTemp|OTG_SEL_HC_DC)); } else { // selct HC otg_reg_read16(REG_OTG_CONTROL, &wTemp); otg_reg_write16(REG_OTG_CONTROL, (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(REG_OTG_CONTROL, &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(REG_OTG_CONTROL, wTemp); } else { otg_reg_read16(REG_OTG_CONTROL, &wTemp); otg_reg_write16(REG_OTG_CONTROL, 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(REG_OTG_CONTROL, &wTemp); otg_reg_write16(REG_OTG_CONTROL, (wTemp|OTG_A_RDIS_LCON_EN));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -