[Bugfix][R306BR][bug-view-1474][USB] use usb detect pin for R306BR, to fix out of skbuff after usb plugin/plugout; old files
Change-Id: I57a61157f14ba706ff1f341b87260e29b355725b
diff --git a/lynq/R306BR/ap/os/linux/linux-3.4.x/drivers/usb/dwc_otg/dwc_otg_chg_identify.c b/lynq/R306BR/ap/os/linux/linux-3.4.x/drivers/usb/dwc_otg/dwc_otg_chg_identify.c
new file mode 100644
index 0000000..6d887bf
--- /dev/null
+++ b/lynq/R306BR/ap/os/linux/linux-3.4.x/drivers/usb/dwc_otg/dwc_otg_chg_identify.c
@@ -0,0 +1,1204 @@
+/* ==========================================================================
+ * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_driver.c $
+ * $Revision: #92 $
+ * $Date: 2012/08/10 $
+ * $Change: 2047372 $
+ *
+ * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
+ * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
+ * otherwise expressly agreed to in writing between Synopsys and you.
+ *
+ * The Software IS NOT an item of Licensed Software or Licensed Product under
+ * any End User Software License Agreement or Agreement for Licensed Product
+ * with Synopsys or any supplement thereto. You are permitted to use and
+ * redistribute this Software in source and binary forms, with or without
+ * modification, provided that redistributions of source code must retain this
+ * notice. You may not view, use, disclose, copy or distribute this file or
+ * any information contained herein except pursuant to this license grant from
+ * Synopsys. If you do not agree with this notice, including the disclaimer
+ * below, then you are not authorized to use the Software.
+ *
+ * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS 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.
+ * ========================================================================== */
+
+/** @file
+ * The dwc_otg_driver module provides the initialization and cleanup entry
+ * points for the DWC_otg driver. This module will be dynamically installed
+ * after Linux is booted using the insmod command. When the module is
+ * installed, the dwc_otg_driver_init function is called. When the module is
+ * removed (using rmmod), the dwc_otg_driver_cleanup function is called.
+ *
+ * This module also defines a data structure for the dwc_otg_driver, which is
+ * used in conjunction with the standard ARM lm_device structure. These
+ * structures allow the OTG driver to comply with the standard Linux driver
+ * model in which devices and drivers are registered with a bus driver. This
+ * has the benefit that Linux can expose attributes of the driver and device
+ * in its special sysfs file system. Users can then read or write files in
+ * this file system to perform diagnostics on the driver components or the
+ * device.
+ */
+
+#include "dwc_otg_os_dep.h"
+#include "dwc_os.h"
+#include "dwc_otg_dbg.h"
+#include "dwc_otg_driver.h"
+#include "dwc_otg_attr.h"
+#include "dwc_otg_cil.h"
+#include "dwc_otg_core_if.h"
+#include "dwc_otg_pcd_if.h"
+#include "dwc_otg_hcd_if.h"
+#include "dwc_otg_pcd.h"
+#include <mach/zx29_usb.h>
+#include <linux/android_notify.h>
+#include <mach/highspeed_debug.h>
+#include <linux/wakelock.h>
+#include <linux/clockchips.h>
+#include <linux/clk.h>
+#include <mach/gpio.h>
+#include <linux/gpio.h>
+#include <mach/pcu.h>
+
+#ifdef USB_CHG_DEV
+#define DWC_DRIVER_VERSION "3.00a 10-AUG-2012"
+#define DWC_DRIVER_DESC "HS OTG USB Controller driver"
+static const char dwc_chg_name[] = "zx297520V3_hsotg";
+#endif
+#define DWC_WRITE_REG32(a,v) ((*(volatile u32 *)(a)) = v)
+#define DWC_READ_REG32(a) (*(volatile u32 *)(a))
+
+#define USE_ASIC 1
+#define DMA_ENABLE 0
+
+extern void usb_notify_up(usb_notify_event notify_type, void* puf);
+//extern void usb_detect_callback(void *buf, unsigned int len);
+//extern void zx297510_usbdev_init(void);
+extern void dwc_chg_udelay(uint32_t usecs);
+extern void dwc_chg_mdelay(uint32_t usecs);
+//extern struct wake_lock dwc_otg_wake_lock;
+
+extern void dwc_otg_hal_init(void);
+extern void dwc_otg_hal_exit(void);
+
+/*-------------------------------------------------------------------------*/
+/* Encapsulate the module parameter settings */
+
+struct dwc_otg_driver_module_params {
+ int32_t opt;
+ int32_t otg_cap;
+ int32_t dma_enable;
+ int32_t dma_desc_enable;
+ int32_t dma_burst_size;
+ int32_t speed;
+ int32_t host_support_fs_ls_low_power;
+ int32_t host_ls_low_power_phy_clk;
+ int32_t enable_dynamic_fifo;
+ int32_t data_fifo_size;
+ int32_t dev_rx_fifo_size;
+ int32_t dev_nperio_tx_fifo_size;
+ uint32_t dev_perio_tx_fifo_size[MAX_PERIO_FIFOS];
+ int32_t host_rx_fifo_size;
+ int32_t host_nperio_tx_fifo_size;
+ int32_t host_perio_tx_fifo_size;
+ int32_t max_transfer_size;
+ int32_t max_packet_count;
+ int32_t host_channels;
+ int32_t dev_endpoints;
+ int32_t phy_type;
+ int32_t phy_utmi_width;
+ int32_t phy_ulpi_ddr;
+ int32_t phy_ulpi_ext_vbus;
+ int32_t i2c_enable;
+ int32_t ulpi_fs_ls;
+ int32_t ts_dline;
+ int32_t en_multiple_tx_fifo;
+ uint32_t dev_tx_fifo_size[MAX_TX_FIFOS];
+ uint32_t thr_ctl;
+ uint32_t tx_thr_length;
+ uint32_t rx_thr_length;
+ int32_t pti_enable;
+ int32_t mpi_enable;
+ int32_t lpm_enable;
+ int32_t ic_usb_cap;
+ int32_t ahb_thr_ratio;
+ int32_t power_down;
+ int32_t reload_ctl;
+ int32_t dev_out_nak;
+ int32_t cont_on_bna;
+ int32_t ahb_single;
+ int32_t otg_ver;
+ int32_t adp_enable;
+};
+
+struct g_data
+{
+ dwc_otg_device_t g_dwc_otg_dev_t;
+ u32 dwRxQuit;
+ u32 dwTxQuit;
+ u32 g_Connet;
+ u32 g_USB_MODE;
+ u32 g_USB_TIMEOUT;
+ u16 g_status_buf;
+ int g_State;
+ int g_bootfinish;
+ int g_bootaddr;
+ int g_bootsize;
+
+ dwc_otg_core_if_t core_if_t;
+ dwc_otg_dev_if_t dev_if_t;
+ dwc_otg_core_params_t g_core_params;
+
+ u32 g_in_pPara[3];
+ u32 g_out_pPara[3];
+// u_setup_pkt g_u_setup_pkt[sizeof(u_setup_pkt)*5];
+ dwc_otg_pcd_t g_dwc_otg_pcd_tp;
+// T_USB_ENUM g_enum;
+ //add by 10136329 for charger or PC
+
+};
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+ int usb_detect_irq;
+ int usb_plugin;
+#endif
+ T_TYPE_USB_DETECT g_plug_in = TYPE_UNKNOWN;
+ usb_detect_callback detect_fn = NULL;
+struct g_data *g_chg_usb_global = NULL;
+
+void dwc_chg_Regcallback(usb_detect_callback fn)
+{
+ USBHAL_DBG("dwc_chg_Regcallback");
+ detect_fn = fn;
+}
+int detected_charger(void)
+{
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+ return 1;
+#endif
+ if(detect_fn == NULL)
+ return 1;
+ else return 0;
+}
+
+
+static void dwc_chg_modify_reg32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
+{
+ DWC_WRITE_REG32(reg,(DWC_READ_REG32(reg) & ~clear_mask) | set_mask);
+}
+
+
+static int dwc_otg_chg_setup_params(dwc_otg_core_if_t * core_if)
+{
+ int i;
+ core_if->core_params = &(g_chg_usb_global->g_core_params);
+ core_if->core_params->otg_cap = DWC_OTG_CAP_PARAM_NO_HNP_SRP_CAPABLE;
+ core_if->core_params->phy_type = DWC_PHY_TYPE_PARAM_UTMI;
+ core_if->core_params->speed = DWC_SPEED_PARAM_HIGH;//DWC_SPEED_PARAM_FULL
+ core_if->core_params->phy_ulpi_ddr = dwc_param_phy_ulpi_ddr_default;
+ core_if->core_params->phy_ulpi_ext_vbus = dwc_param_phy_ulpi_ext_vbus_default;
+ core_if->core_params->phy_utmi_width = 8;
+ core_if->core_params->ts_dline = dwc_param_ts_dline_default;
+ core_if->core_params->ulpi_fs_ls = dwc_param_ulpi_fs_ls_default;
+ core_if->core_params->en_multiple_tx_fifo = dwc_param_en_multiple_tx_fifo_default;
+
+ core_if->core_params->dma_enable = dwc_param_dma_enable_default;
+ core_if->core_params->dma_desc_enable = dwc_param_dma_desc_enable_default;
+ core_if->core_params->max_transfer_size = dwc_param_max_transfer_size_default;
+ core_if->core_params->dma_burst_size = dwc_param_dma_burst_size_default;
+
+ for (i = 0; i < 15; i++)
+ {
+ core_if->core_params->dev_tx_fifo_size[i] = dwc_param_dev_tx_fifo_size_default;
+ }
+ core_if->core_params->otg_ver = 1;
+ return 0;
+}
+
+dwc_otg_core_if_t *dwc_otg_chg_cil_init(const uint32_t * reg_base_addr)
+{
+ dwc_otg_core_if_t *core_if = &(g_chg_usb_global->core_if_t);
+ dwc_otg_dev_if_t *dev_if = &(g_chg_usb_global->dev_if_t);
+ uint8_t *pt_core_if = ( uint8_t *)&(g_chg_usb_global->core_if_t);
+ uint8_t *pt_dev_if = ( uint8_t *)&(g_chg_usb_global->dev_if_t);
+ uint8_t *reg_base = (uint8_t *) reg_base_addr;
+ int i = 0;
+ for(i= 0;i<sizeof(g_chg_usb_global->core_if_t);i++)
+ {
+ pt_core_if[i] = 0;
+ }
+ core_if->core_global_regs = (dwc_otg_core_global_regs_t *) reg_base;
+
+ for(i= 0;i<sizeof(g_chg_usb_global->dev_if_t);i++)
+ {
+ pt_dev_if[i] = 0;
+ }
+
+ dev_if->dev_global_regs = (dwc_otg_device_global_regs_t *) (reg_base +DWC_DEV_GLOBAL_REG_OFFSET);
+
+ for (i = 0; i < MAX_EPS_CHANNELS; i++)
+ {
+ dev_if->in_ep_regs[i] = (dwc_otg_dev_in_ep_regs_t *)
+ (reg_base + DWC_DEV_IN_EP_REG_OFFSET +
+ (i * DWC_EP_REG_OFFSET));
+
+ dev_if->out_ep_regs[i] = (dwc_otg_dev_out_ep_regs_t *)
+ (reg_base + DWC_DEV_OUT_EP_REG_OFFSET +
+ (i * DWC_EP_REG_OFFSET));
+
+ core_if->data_fifo[i] =(uint32_t *) (reg_base + DWC_OTG_DATA_FIFO_OFFSET +(i * DWC_OTG_DATA_FIFO_SIZE));
+ }
+
+ dev_if->speed = 0;
+
+ core_if->dev_if = dev_if;
+
+ core_if->pcgcctl = (uint32_t *) (reg_base + DWC_OTG_PCGCCTL_OFFSET);
+
+ core_if->hwcfg1.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg1);
+ core_if->hwcfg2.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg2);
+ core_if->hwcfg3.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg3);
+ core_if->hwcfg4.d32 =DWC_READ_REG32(&core_if->core_global_regs->ghwcfg4);
+
+ core_if->dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+
+ core_if->snpsid = DWC_READ_REG32(&core_if->core_global_regs->gsnpsid);
+
+ dwc_otg_chg_setup_params(core_if);
+
+
+ return core_if;
+}
+
+/**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+ /**
+ * Initializes the DevSpd field of the DCFG register depending on the PHY type
+ * and the enumeration speed of the device.
+ */
+static void init_chg_devspd(dwc_otg_core_if_t * core_if,uint8_t speed)
+{
+ uint32_t val;
+ dcfg_data_t dcfg;
+
+ val = speed;
+ dcfg.d32 = DWC_READ_REG32(&core_if->dev_if->dev_global_regs->dcfg);
+ dcfg.b.devspd = val;
+ DWC_WRITE_REG32(&core_if->dev_if->dev_global_regs->dcfg, dcfg.d32);
+}
+
+/**
+ * Flush a Tx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ * @param num Tx FIFO to flush.
+ */
+void dwc_otg_chg_flush_tx_fifo(dwc_otg_core_if_t * core_if, const int num)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset;
+ int count = 0;
+ greset.d32 = 0;
+
+ greset.b.txfflsh = 1;
+ greset.b.txfnum = num;
+
+{
+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+ do
+ {
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 10000)
+ {
+ break;
+ }
+ dwc_chg_udelay(10);
+ }
+ while (greset.b.txfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+ dwc_chg_udelay(10);
+}
+
+}
+
+/**
+ * Flush Rx FIFO.
+ *
+ * @param core_if Programming view of DWC_otg controller.
+ */
+void dwc_otg_chg_flush_rx_fifo(dwc_otg_core_if_t * core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset;
+ int count = 0;
+ greset.d32 = 0;
+ greset.b.rxfflsh = 1;
+
+{
+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+
+ do
+ {
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 10000)
+ {
+ break;
+ }
+ dwc_chg_udelay(10);
+ }
+ while (greset.b.rxfflsh == 1);
+
+ /* Wait for 3 PHY Clocks */
+
+ dwc_chg_udelay(10);
+}
+}
+
+/**
+ * This function initializes the DWC_otg controller registers for
+ * device mode.
+ *
+ * @param core_if Programming view of DWC_otg controller
+ *
+ */
+void dwc_otg_chg_core_dev_init(dwc_otg_core_if_t * core_if)
+{
+ int i;
+// T_TYPE_USB_DETECT chgtype;
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ dcfg_data_t dcfg;
+ grstctl_t resetctl;
+ dctl_data_t dctl;
+ diepmsk_data_t msk;
+ dcfg.d32 = 0;
+ resetctl.d32 = 0;
+ dctl.d32 = 0;
+ msk.d32 = 0;
+ /* Restart the Phy Clock */
+ DWC_WRITE_REG32(core_if->pcgcctl, 0);
+
+ /* Device configuration register */
+ init_chg_devspd(core_if,0);//ĬÈÏÅäÖóɸßËÙ
+ dcfg.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dcfg);
+ dcfg.b.descdma = 0;
+ dcfg.b.perfrint = DWC_DCFG_FRAME_INTERVAL_80;
+
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dcfg, dcfg.d32);
+
+ /* Flush the FIFOs */
+ dwc_otg_chg_flush_tx_fifo(core_if, 0x10); /* all Tx FIFOs */
+ dwc_otg_chg_flush_rx_fifo(core_if);
+
+ /* Flush the Learning Queue. */
+ resetctl.b.intknqflsh = 1;
+ DWC_WRITE_REG32(&core_if->core_global_regs->grstctl, resetctl.d32);
+ /* Clear all pending Device Interrupts */
+ /** @todo - if the condition needed to be checked
+ * or in any case all pending interrutps should be cleared?
+ */
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->diepmsk, 0);
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->doepmsk, 0);
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daint, 0xFFFFFFFF);
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->daintmsk, 0);
+
+ for (i = 0; i <= dev_if->num_in_eps; i++)
+ {
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepctl,0);
+
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->dieptsiz, 0);
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepdma, 0);
+ DWC_WRITE_REG32(&dev_if->in_ep_regs[i]->diepint, 0xFF);
+
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepctl,0);
+
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doeptsiz, 0);
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepdma, 0);
+ USBHAL_DBG("%s, %u doepdmadbg i:%d", __func__, __LINE__, i);
+ DWC_WRITE_REG32(&dev_if->out_ep_regs[i]->doepint, 0xFF);
+ }
+ msk.b.txfifoundrn = 1;
+ dwc_chg_modify_reg32(&dev_if->dev_global_regs->diepmsk,msk.d32, msk.d32);
+ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+ dctl.b.sftdiscon = 0;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+
+ #if 1
+ for(i = 0;i<3;i++)
+ {
+ dwc_chg_mdelay(30);
+ if((((DWC_READ_REG32(&dev_if->dev_global_regs->dsts))>>22)&0x3) ==3)
+ {
+ g_plug_in = TYPE_ADAPTER;
+ }
+ else
+ {
+ g_plug_in = TYPE_COMPUTER;
+ break;
+ }
+ }
+ // if(g_plug_in == TYPE_ADAPTER)
+ // WARN_ON(1);
+ #else
+ dwc_chg_mdelay(100);
+ if((((DWC_READ_REG32(&dev_if->dev_global_regs->dsts))>>22)&0x3) ==3)
+ {
+ g_plug_in = TYPE_ADAPTER;
+ USBHAL_DBG("usb-dwc deteck TYPE_ADAPTER");
+
+// chgtype = TYPE_ADAPTER;
+// usb_detect_callback(&chgtype, 0);
+ }else
+ {
+ g_plug_in = TYPE_COMPUTER;
+ USBHAL_DBG("usb-dwc deteck TYPE_COMPUTER");
+// chgtype = TYPE_COMPUTER;
+// usb_detect_callback(&chgtype, 0);
+ }
+ #endif
+
+ if(detect_fn)
+ {
+ USBHAL_DBG("usb-dwc callback");
+ detect_fn(g_plug_in);
+ }
+
+ dctl.d32 = DWC_READ_REG32(&dev_if->dev_global_regs->dctl);
+ dctl.b.sftdiscon = 1;
+ DWC_WRITE_REG32(&dev_if->dev_global_regs->dctl, dctl.d32);
+}
+
+/**
+ * Do core a soft reset of the core. Be careful with this because it
+ * resets all the internal state machines of the core.
+ */
+void dwc_otg_chg_core_reset(dwc_otg_core_if_t * core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ volatile grstctl_t greset;
+ int count = 0;
+ greset.d32 =0;
+ /* Wait for AHB master IDLE state. */
+ do
+ {
+ dwc_chg_udelay(10);
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 100000)
+ {
+ return;
+ }
+ }
+ while (greset.b.ahbidle == 0);
+
+ /* Core Soft Reset */
+ count = 0;
+ greset.b.csftrst = 1;
+ DWC_WRITE_REG32(&global_regs->grstctl, greset.d32);
+ do
+ {
+ greset.d32 = DWC_READ_REG32(&global_regs->grstctl);
+ if (++count > 10000)
+ {
+ break;
+ }
+ dwc_chg_udelay(10);
+ }
+ while (greset.b.csftrst == 1);
+/* Wait for 3 PHY Clocks */
+ dwc_chg_udelay(10);
+}
+
+/**
+ * This function initializes the DWC_otg controller registers and
+ * prepares the core for device mode or host mode operation.
+ *
+ * @param core_if Programming view of the DWC_otg controller
+ *
+ */
+void dwc_otg_chg_core_init(dwc_otg_core_if_t * core_if)
+{
+ dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
+ dwc_otg_dev_if_t *dev_if = core_if->dev_if;
+ gahbcfg_data_t ahbcfg;
+ gotgctl_data_t gotgctl;
+
+ gusbcfg_data_t usbcfg;
+ ahbcfg.d32 = 0;
+ usbcfg.d32 = 0;
+ gotgctl.d32 = 0;
+
+
+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+
+{
+
+#if !USE_ASIC
+ usbcfg.b.ulpi_ext_vbus_drv =(core_if->core_params->phy_ulpi_ext_vbus == DWC_PHY_ULPI_EXTERNAL_VBUS) ? 1 : 0;
+
+ usbcfg.b.term_sel_dl_pulse = (core_if->core_params->ts_dline == 1) ? 1 : 0;
+
+
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+#endif
+ dwc_otg_chg_core_reset(core_if);
+ }
+
+
+ dev_if->num_in_eps = 2;//calc_num_in_eps(core_if);
+ dev_if->num_out_eps = 2;//calc_num_out_eps(core_if);
+
+ core_if->total_fifo_size = core_if->hwcfg3.b.dfifo_depth;
+ core_if->rx_fifo_size = DWC_READ_REG32(&global_regs->grxfsiz);
+ core_if->nperio_tx_fifo_size = DWC_READ_REG32(&global_regs->gnptxfsiz) >> 16;
+ {
+ /* High speed PHY. */
+ if (!core_if->phy_init_done)
+ {
+ core_if->phy_init_done = 1;
+ /* HS PHY parameters. These parameters are preserved
+ * during soft reset so only program the first time. Do
+ * a soft reset immediately after setting phyif. */
+ #if !USE_ASIC
+ if (core_if->core_params->phy_type == 2)
+ {
+ /* ULPI interface */
+ usbcfg.b.ulpi_utmi_sel = 1;
+ usbcfg.b.phyif = 0;
+ usbcfg.b.ddrsel = core_if->core_params->phy_ulpi_ddr;
+ }
+ #else
+ if (core_if->core_params->phy_type == 1)
+ {
+ /* UTMI+ interface */
+ usbcfg.b.ulpi_utmi_sel = 0;
+ if (core_if->core_params->phy_utmi_width == 16)
+ {
+ usbcfg.b.phyif = 1;
+
+ }
+ else
+ {
+ usbcfg.b.phyif = 0;
+ }
+ }
+ #endif
+
+ {
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+ /* Reset after setting the PHY parameters */
+ dwc_otg_chg_core_reset(core_if);
+ }
+ }
+ }
+
+ {
+#if !USE_ASIC
+ if ((core_if->hwcfg2.b.hs_phy_type == 2) &&(core_if->hwcfg2.b.fs_phy_type == 1) &&(core_if->core_params->ulpi_fs_ls))
+ {
+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 1;
+ usbcfg.b.ulpi_clk_sus_m = 1;
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+ }
+ else
+ {
+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+ usbcfg.b.ulpi_fsls = 0;
+ usbcfg.b.ulpi_clk_sus_m = 0;
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+ }
+#endif
+ }
+#if DMA_ENABLE
+ /* Program the GAHBCFG Register. */
+ switch (core_if->hwcfg2.b.architecture)
+ {
+ case DWC_SLAVE_ONLY_ARCH:
+
+ //ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ // ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
+ ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ core_if->dma_enable = 0;
+ core_if->dma_desc_enable = 0;
+ break;
+
+ case DWC_EXT_DMA_ARCH:
+ {
+ uint8_t brst_sz = core_if->core_params->dma_burst_size;
+ ahbcfg.b.hburstlen = 0;
+ while (brst_sz > 1)
+ {
+ ahbcfg.b.hburstlen++;
+ brst_sz >>= 1;
+ }
+ }
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ core_if->dma_desc_enable = (core_if->core_params->dma_desc_enable != 0);
+ break;
+
+ case DWC_INT_DMA_ARCH:
+ /* Old value was DWC_GAHBCFG_INT_DMA_BURST_INCR - done for
+ Host mode ISOC in issue fix - vahrama */
+ ahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR4;
+ core_if->dma_enable = (core_if->core_params->dma_enable != 0);
+ core_if->dma_desc_enable = (core_if->core_params->dma_desc_enable != 0);
+ break;
+
+ }
+ if (core_if->dma_enable)
+ {
+ if (core_if->dma_desc_enable)
+ {
+ printf("Using Descriptor DMA mode\n");
+ }
+ else
+ {
+ printf("using buffer dma mode\n");
+
+ }
+ }
+ else
+ {
+ printf("Using Slave mode\n");
+
+ core_if->dma_desc_enable = 0;
+ }
+ ahbcfg.b.dmaenable = core_if->dma_enable;
+ #else
+ ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+ ahbcfg.b.ptxfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_HALFEMPTY;
+
+
+ ahbcfg.b.dmaenable = 0;
+// ÅäÖÃÈ«¿ÕFIFO²úÉúÖжÏ
+ ahbcfg.b.nptxfemplvl_txfemplvl = DWC_GAHBCFG_TXFEMPTYLVL_EMPTY ;
+#endif
+
+ DWC_WRITE_REG32(&global_regs->gahbcfg, ahbcfg.d32);
+
+ core_if->en_multiple_tx_fifo = core_if->hwcfg4.b.ded_fifo_en;
+
+ core_if->pti_enh_enable = core_if->core_params->pti_enable != 0;
+ core_if->multiproc_int_enable = dwc_param_mpi_enable_default;//core_if->core_params->mpi_enable;
+ /*
+ * Program the GUSBCFG register.
+ */
+ usbcfg.d32 = DWC_READ_REG32(&global_regs->gusbcfg);
+ usbcfg.b.hnpcap = 0;
+ usbcfg.b.srpcap = 0;
+
+ DWC_WRITE_REG32(&global_regs->gusbcfg, usbcfg.d32);
+
+ gotgctl.b.otgver = core_if->core_params->otg_ver;
+
+ dwc_chg_modify_reg32(&core_if->core_global_regs->gotgctl, 0, gotgctl.d32);
+
+ /* Set OTG version supported */
+ core_if->otg_ver = core_if->core_params->otg_ver;
+
+ dwc_otg_chg_core_dev_init(core_if);
+}
+
+struct platform_device *zx297510_platform_chg_usb_dev;
+
+#ifdef USB_CHG_DEV
+static int dwc_otg_chg_driver_probe(struct platform_device *_dev)
+{
+ zx297510_platform_chg_usb_dev = _dev;
+ return 0;
+}
+
+static void dwc_otg_chg_driver_remove( struct platform_device *_dev)
+{
+}
+
+static struct platform_driver dwc_otg_chg_driver = {
+ .driver = {
+ .name = (char *)dwc_chg_name,
+ .bus = &platform_bus_type,
+ .owner = THIS_MODULE,
+ //.pm = DWC_OTG_PM_OPS,
+ },
+ .probe = dwc_otg_chg_driver_probe,
+ .remove = __exit_p(dwc_otg_chg_driver_remove),
+};
+#endif
+uint32_t dwc_otg_chg_get_gsnpsid(dwc_otg_core_if_t * core_if)
+{
+ return core_if->snpsid;
+}
+
+/**
+ * This function is called when an lm_device is bound to a
+ * dwc_otg_driver. It creates the driver components required to
+ * control the device (CIL, HCD, and PCD) and it initializes the
+ * device. The driver components are stored in a dwc_otg_device
+ * structure. A reference to the dwc_otg_device is saved in the
+ * lm_device. This allows the driver to access the dwc_otg_device
+ * structure on subsequent calls to driver methods for this device.
+ *
+ * @param _dev Bus device
+ */
+//extern int dwc_otg_open_power(void);
+//extern int dwc_otg_close_power(void);
+#ifdef USB_CHG_DEV
+int dwc_otg_usb_chg_detect(struct platform_device *_dev)
+{
+ int retval = 0;
+ struct clk* wclk;
+ struct clk* pclk;
+ struct resource *iomem;
+
+ dwc_otg_device_t *dwc_otg_device = (g_chg_usb_global->g_dwc_otg_dev_t);
+
+ iomem = platform_get_resource(_dev, IORESOURCE_MEM,0);
+
+ dev_dbg(&_dev->dev, "start=0x%08x\n", (unsigned)iomem->start);
+
+ memset(dwc_otg_device, 0, sizeof(dwc_otg_device_t));
+ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
+
+ dwc_otg_device->os_dep.regs_res = request_mem_region(iomem->start, resource_size(iomem),
+ dev_name(_dev));
+ dwc_otg_device->os_dep.base= ioremap(iomem->start, resource_size(iomem));
+
+ if (!dwc_otg_device->os_dep.base) {
+ dev_err(&_dev->dev, "ioremap() failed\n");
+ return -ENOMEM;
+ }
+
+ /*
+ * Initialize driver data to point to the global DWC_otg
+ * Device structure.
+ */
+ platform_set_drvdata(_dev, dwc_otg_device);
+
+ dev_dbg(&_dev->dev, "dwc_otg_device=0x%p\n", dwc_otg_device);
+
+/*
+ Please ensure power on the USB controller and Phy
+*/
+#if 0
+ zx29_usbdev_init(); //
+ retval = dwc_otg_open_power();
+#endif
+
+ pclk = clk_get(&_dev->dev, "ahb_clk");
+ if(IS_ERR(pclk) ){
+ return -EIO;
+ }
+
+ wclk = clk_get(&_dev->dev, "work_clk");
+
+ if(IS_ERR(pclk) ){
+ return -EIO;
+ }
+
+ clk_enable(pclk);
+ clk_enable(wclk);
+
+#if 1
+ zx29_usbdev_init();
+ retval = dwc_otg_open_power();
+#endif
+
+ dwc_otg_device->core_if = dwc_otg_chg_cil_init(dwc_otg_device->os_dep.base);
+ if (!dwc_otg_device->core_if) {
+ dev_err(&_dev->dev, "CIL initialization failed!\n");
+ retval = -ENOMEM;
+ goto fail;
+ }
+ if (((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) &&
+ ((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
+ dev_err(&_dev->dev, "%s, Bad value for SNPSID: 0x%08x\n",__func__,
+ dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if));
+ retval = -EINVAL;
+ goto fail;
+ }
+
+ dwc_otg_chg_core_init(dwc_otg_device->core_if);
+
+ clk_disable(wclk);
+ clk_disable(pclk);
+ clk_put(wclk);
+ clk_put(pclk);
+
+ retval = dwc_otg_close_power();
+
+ /*
+ * Return the memory.
+ */
+
+ if(dwc_otg_device->os_dep.regs_res){
+ release_resource(dwc_otg_device->os_dep.regs_res);
+ kfree(dwc_otg_device->os_dep.regs_res);
+ }
+ if (dwc_otg_device->os_dep.base) {
+ iounmap(dwc_otg_device->os_dep.base);
+ }
+
+ /*
+ * Clear the drvdata pointer.
+ */
+ platform_set_drvdata(_dev, 0);
+
+ platform_driver_unregister(&dwc_otg_chg_driver);
+
+ if (g_plug_in == TYPE_ADAPTER)
+ {
+ usb_notify_up(USB_CHARGER_PLUGIN, NULL);
+ }
+ else
+ {
+ usb_notify_up(USB_DEVICE_PLUGIN, NULL);
+ }
+ usb_printk("%s, detect done plunin:%d\n", __func__, g_plug_in);
+fail:
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(dwc_otg_usb_chg_detect);
+#else
+
+
+
+int dwc_otg_usb_chg_detect(void)
+{
+ int retval = 0;
+ struct clk* wclk;
+ struct clk* pclk;
+ struct resource iomem;
+ unsigned int value;
+ g_chg_usb_global = (struct g_data *)kmalloc(sizeof(struct g_data), GFP_KERNEL);
+ if(g_chg_usb_global == NULL){
+ g_chg_usb_global = (struct g_data *)kmalloc(sizeof(struct g_data), GFP_KERNEL);
+ if(g_chg_usb_global == NULL){
+ printk("fetal error alloc g_chg_usb_global fail\n");
+ WARN_ON(1);
+ return -1;
+ }
+ }
+
+ memset(g_chg_usb_global, 0, sizeof(struct g_data));
+
+ dwc_otg_device_t *dwc_otg_device = &(g_chg_usb_global->g_dwc_otg_dev_t);
+
+ memset(dwc_otg_device, 0, sizeof(dwc_otg_device_t));
+ dwc_otg_device->os_dep.reg_offset = 0xFFFFFFFF;
+ iomem.start = ZX29_USB_PHYS;// change by gsn
+ iomem.end = ZX29_USB_PHYS+SZ_256K-1;// change by gsn
+#if 1
+ dwc_otg_device->os_dep.base= ioremap(iomem.start, resource_size(&iomem));
+#else
+ dwc_otg_device->os_dep.base = ZX29_USB1_CFG_BASE_VA;
+#endif
+ if(!dwc_otg_device->os_dep.base)
+ {
+ retval = -ENOMEM;
+ goto fail;
+ }
+/*
+ Please ensure power on the USB controller and Phy
+*/
+ dwc_otg_hal_init();
+
+ dwc_chg_udelay(10);
+
+ dwc_otg_device->core_if = dwc_otg_chg_cil_init(dwc_otg_device->os_dep.base);
+ if (!dwc_otg_device->core_if) {
+ printk(KERN_ERR "%s, CIL initialization failed!\n", __func__);
+ retval = -ENOMEM;
+ goto fail;
+ }
+ if (((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) &&
+ ((dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) {
+ printk(KERN_ERR "%s, Bad value for SNPSID: 0x%08x\n",__func__,
+ dwc_otg_chg_get_gsnpsid(dwc_otg_device->core_if));
+ retval = -EINVAL;
+ goto fail;
+ }
+
+ dwc_otg_chg_core_init(dwc_otg_device->core_if);
+
+ dwc_otg_hal_exit();
+ printk("dwc_otg_usb_chg_detect, g_plug_in:%d, type:%s\n", g_plug_in, (g_plug_in == 1 ? "pc" : "adapter"));
+ if (g_plug_in == TYPE_ADAPTER)
+ {
+ usb_notify_up(USB_CHARGER_PLUGIN, NULL);
+ }
+ else
+ {
+ usb_notify_up(USB_DEVICE_PLUGIN, NULL);
+// wake_lock(&dwc_otg_wake_lock);
+ dwc_otg_wakelock(1,1);
+ }
+
+fail:
+ if (dwc_otg_device->os_dep.base)
+ {
+#if 1
+ iounmap(dwc_otg_device->os_dep.base);
+#endif
+ }
+ kfree(g_chg_usb_global);
+ g_chg_usb_global = NULL;
+
+ return 0;
+
+}
+EXPORT_SYMBOL_GPL(dwc_otg_usb_chg_detect);
+
+#endif
+int dwc_otg_usb_chg_remove(void)
+{
+ if (g_plug_in == TYPE_ADAPTER)
+ {
+ usb_notify_up(USB_CHARGER_PLUGOUT, NULL);
+ }
+ else
+ {
+ usb_notify_up(USB_DEVICE_PLUGOUT, NULL);
+// wake_unlock(&dwc_otg_wake_lock);
+ //dwc_otg_wakelock(0,0);
+ }
+ g_plug_in = TYPE_UNKNOWN;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dwc_otg_usb_chg_remove);
+
+
+void dwc_otg_chg_inform(int inform)
+{
+ if(inform == 0)
+ dwc_otg_usb_chg_detect();
+ else if(inform == 1)
+ dwc_otg_usb_chg_remove();
+ else
+ USBHAL_DBG("dwc_otg_chg_inform %d", inform);
+}
+EXPORT_SYMBOL_GPL(dwc_otg_chg_inform);
+
+int dwc_otg_chg_inform_type(int inform)
+{
+ int chg_type = 0;
+ if(inform == 0){
+ dwc_otg_usb_chg_detect();
+ if (g_plug_in == TYPE_ADAPTER){
+ chg_type = 0;
+ }else{
+ chg_type = 1;
+ }
+ }
+ else if(inform == 1)
+ dwc_otg_usb_chg_remove();
+ else
+ USBHAL_DBG("dwc_otg_chg_inform %d", inform);
+ return chg_type;
+}
+EXPORT_SYMBOL_GPL(dwc_otg_chg_inform_type);
+#ifdef USB_CHG_DEV
+
+struct platform_device *get_chg_usb_platform_device(void)
+{
+ usb_printk("%s, dev:%p, name:%s\n", __func__, zx297510_platform_chg_usb_dev, zx297510_platform_chg_usb_dev->name);
+ return zx297510_platform_chg_usb_dev;
+}
+EXPORT_SYMBOL_GPL(get_chg_usb_platform_device);
+
+static int __init dwc_otg_chg_init(void)
+{
+ int retval = 0;
+ int error;
+
+ usb_printk("%s, %s: version %s\n", __func__, dwc_chg_name,
+ DWC_DRIVER_VERSION);
+
+ retval = platform_driver_register(&dwc_otg_chg_driver);
+
+
+ if (retval < 0) {
+ printk(KERN_ERR "%s retval=%d\n", __func__, retval);
+ return retval;
+ }
+ return retval;
+}
+
+module_init(dwc_otg_chg_init);
+#endif
+#ifdef CONFIG_DWC_DEVICE_GPIO_CHARGER
+extern unsigned int get_usb_gpio_detect_flag(void);
+//wangzhen
+extern int dwc_otg_disconnect(void);
+/*GPIOºÍÍⲿÖжϺŸù¾ÝÏîĿʵ¼ÊÇé¿öÐÞ¸Ä
+ *´Ë´¦Îª²Î¿¼´úÂë
+ */
+#define USB_GPIO ZX29_GPIO_52
+#define USB_GPIO_FUNC_GPIO GPIO52_GPIO52
+#define USB_GPIO_FUNC_EXT_INT GPIO52_EXT_INT5
+#define USB_DT_INT PCU_EX5_INT
+
+int Usb_Detect_Val(void)
+{
+ int value;
+
+ value = gpio_get_value(USB_GPIO);
+
+ return value;
+}
+EXPORT_SYMBOL_GPL(Usb_Detect_Val);
+
+irqreturn_t Usb_Detect_Irq_Handler(int irq, struct platform_device *_dev)
+{
+ printk(KERN_INFO"%s,end\n", __func__);
+ pcu_int_clear(USB_DT_INT);
+ //dwc_otg_wakelock(1,0);
+ return IRQ_WAKE_THREAD;
+}
+
+irqreturn_t Usb_Detect_Irq_Thread(int irq, struct platform_device *_dev)
+{
+ int ret = -1;
+ int irq_num;
+ int retval;
+ int value;
+ unsigned int gpio_enable = 0;
+ struct sched_param param = { .sched_priority = 2 };
+ param.sched_priority= 33;
+ sched_setscheduler(current, SCHED_FIFO, ¶m);
+ gpio_enable = get_usb_gpio_detect_flag();
+ printk("Usb_Detect_Irq_Thread, gpio_enable:%d\n", gpio_enable);
+ if(gpio_enable == 0)
+ return IRQ_HANDLED;
+
+ dwc_otg_wakelock(1,0);
+ //5.23
+ zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_GPIO);
+ gpio_direction_input(USB_GPIO);
+ msleep(5);
+ value = gpio_get_value(USB_GPIO);
+ printk("%s,value:%d\n", __func__,value);
+ zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_EXT_INT);
+
+ if(value == 1)
+ {
+ zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_FALLING);
+ pcu_int_clear(USB_DT_INT);
+ if(usb_plugin == 1){
+ dwc_otg_disconnect();
+ dwc_otg_usb_chg_remove(); //not plug in;
+ usb_plugin = 0;
+ }
+ }
+ else
+ {
+ zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_RISING);
+ pcu_int_clear(USB_DT_INT);
+ if(usb_plugin == 0){
+ dwc_otg_usb_chg_detect(); //plug in;
+ usb_plugin = 1;
+ }
+ }
+ printk(KERN_INFO"%s,value:%d,end\n", __func__,value);
+ USBSTACK_DBG("%s,value:%d", __func__,value);
+ return IRQ_HANDLED;
+}
+
+static void usb_detect_typedet(T_TYPE_USB_DETECT chg_type)
+{
+ printk("register usb_detect_typedet for charger\n");
+}
+
+int Usb_Detect_Irq_probe(struct platform_device *_dev)
+{
+ USBSTACK_DBG("%s", __func__);
+ int ret = -1;
+ int value;
+ int value2 = 0;
+
+ printk("-----------Usb_Detect_Irq_probe\n");
+ dwc_chg_Regcallback(usb_detect_typedet);
+
+ ret = gpio_request(USB_GPIO, "usb");
+ zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_GPIO);
+ gpio_direction_input(USB_GPIO);
+ zx29_gpio_pd_pu_set(USB_GPIO,IO_CFG_PULL_DISABLE);
+ gpio_export(USB_GPIO, 1);
+ mdelay(5);
+ value = gpio_get_value(USB_GPIO);
+ USBSTACK_DBG("%s,value:%d", __func__,value);
+ usb_detect_irq= gpio_to_irq(USB_GPIO);
+ printk(KERN_INFO "%s,value:%d, irq_num:%d\n",__func__,value, usb_detect_irq);
+
+ zx29_gpio_config(USB_GPIO,USB_GPIO_FUNC_EXT_INT);
+#if 1
+ if(value == 1)
+ {
+ usb_plugin = 0;
+ zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_FALLING);
+ }
+ else
+ {
+ dwc_otg_usb_chg_detect(); //plug in;
+ usb_plugin = 1;
+ zx29_gpio_set_inttype(USB_GPIO,IRQ_TYPE_EDGE_RISING);
+ }
+#endif
+ pcu_int_clear(USB_DT_INT);
+ ret = request_threaded_irq(usb_detect_irq, Usb_Detect_Irq_Handler,Usb_Detect_Irq_Thread,IRQF_ONESHOT,
+ "usb", _dev);
+
+ printk(KERN_INFO "%s,ret:%d\n",__func__,ret);
+ if (ret)
+ {
+ printk(KERN_INFO"cannot request Usb_Detect_Irq\n");
+ return ret;
+ }
+
+ irq_set_irq_wake(usb_detect_irq, 1);
+
+ return 0;
+
+}
+
+static int usb_detect_suspend(void)
+{
+ disable_irq(usb_detect_irq);
+ return 0;
+}
+
+static int usb_detect_resume(void)
+{
+ enable_irq(usb_detect_irq);
+ return 0;
+}
+
+static struct platform_driver usb_detect_platform_driver = {
+ .probe = Usb_Detect_Irq_probe,
+ .driver = {
+ .name = "usb_detect",
+ .owner = THIS_MODULE,
+ },
+ .suspend = usb_detect_suspend,
+ .resume = usb_detect_resume,
+};
+
+static int __init usb_detect_init(void)
+{
+ printk("-----------usb_detect_init\n");
+ return platform_driver_register(&usb_detect_platform_driver);
+}
+
+module_init(usb_detect_init);
+
+#endif
\ No newline at end of file
diff --git a/lynq/R306BR/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c b/lynq/R306BR/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
new file mode 100755
index 0000000..649d5ec
--- /dev/null
+++ b/lynq/R306BR/ap/os/linux/linux-3.4.x/drivers/usb/gadget/usb_netlink.c
@@ -0,0 +1,857 @@
+
+/*
+|| sanchips add: xjy@20150312 for usbconfig-hotplug
+*/
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+
+#include <linux/init.h>
+
+#include <linux/string.h>
+
+#include <linux/sysfs.h>
+
+#include <linux/stat.h>
+#include <linux/slab.h>
+#include <linux/kobject.h>
+#include <linux/android_notify.h>
+#include <mach/highspeed_debug.h>
+#include <mach/iomap.h>
+
+extern int detected_charger(void);
+static unsigned int charger_plug = 0;
+static unsigned int usb_plug = 0;
+//static unsigned int sys_id = 1;//0 is windows, other value not windows(mac or linux)
+static unsigned int en_mods = 0;//enable mods
+//static unsigned int auto_eject_ms = 0;
+unsigned int hotplug_flag = 1;
+unsigned int usb_printk_en = 1;
+EXPORT_SYMBOL_GPL(usb_printk_en);
+unsigned int mmc_printk_en = 1;
+unsigned int gmac_printk_en = 1;
+
+unsigned int force_net = 0;
+unsigned int set_panic = 0;
+//for auto test,mdl dev with gpio detect usb plug in/out
+unsigned int usb_gpio_detect_enable = 0;
+//add by gsn, to avoid usb in vincPkt_list backlogged many Skb, set a limit
+unsigned int rndis_vplist_max = 800;
+
+static unsigned int ramdump_flag = 0;
+#define RNDIS_NUM 4
+unsigned int usblan[RNDIS_NUM] = {0,0,0,0};
+
+#define CHARGER_PLUG_NAME "chargerPlug"
+#define USB_PLUG_NAME "usbPlug"
+#define SYS_ID_NAME "sysId"
+#define ENABLE_MODS "enMods"
+#define NET_NAME "netname"
+#define NET0_STATE "usblan0"
+#define NET1_STATE "usblan1"
+#define NET2_STATE "usblan2"
+#define NET3_STATE "usblan3"
+#define HOT_PLUG "hotplug"
+#define USB_PRINTK_EN "usb"
+#define MMC_PRINTK_EN "mmc"
+#define GMAC_PRINTK_EN "gmac"
+
+#define FORCE_NET "forcenet"
+#define SET_PANIC "set_panic"
+#define RAMDUMP_FLAG "ramdumpFlag"
+#define RNDIS_VPLST_MAX "lstmax"
+#define USB_GPIO_DETECT_ENABLE "gpio_detect"
+
+#define USB_LOG_MEM_SIZE (15*1000)
+#define USB_LOG_MAX_SIZE 512
+
+static char s_usbMemLog[USB_LOG_MEM_SIZE]= {0};
+static char *s_localStringBuf = NULL;
+static int s_usbMemLogIndex=0;
+#define SET_ERARLY_SUSPEND_PANIC 0x00000001
+#define SET_BNA_ERR_PANIC 0x00000002
+#define SET_TX_REQ_USEUP_PANIC 0x00000004
+#define SET_RNDIS_RESET_MSG_PANIC 0x00000008
+
+
+static struct attribute charger_plug_attr =
+{
+ .name = "chargerPlug",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute usb_plug_attr =
+{
+ .name = "usbPlug",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute sys_id_attr =
+{
+ .name = "sysId",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute en_mods_attr =
+{
+ .name = "enMods",
+ .mode = S_IRUGO|S_IWUSR,
+};
+static struct attribute ramdump_flag_attr =
+{
+ .name = "ramdumpFlag",
+ .mode = S_IRUGO|S_IWUSR,
+};
+static struct attribute net_name_attr =
+{
+ .name = "netname",
+ .mode = S_IRUGO|S_IWUSR,
+};
+static struct attribute net0_state_attr =
+{
+ .name = "usblan0",
+ .mode = S_IRUGO|S_IWUSR,
+};
+static struct attribute net1_state_attr =
+{
+ .name = "usblan1",
+ .mode = S_IRUGO|S_IWUSR,
+};
+static struct attribute net2_state_attr =
+{
+ .name = "usblan2",
+ .mode = S_IRUGO|S_IWUSR,
+};
+static struct attribute net3_state_attr =
+{
+ .name = "usblan3",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute hotplug_state_attr =
+{
+ .name = "hotplug",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute force_net_attr =
+{
+ .name = "forcenet",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute set_panic_attr =
+{
+ .name = "set_panic",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+
+static struct attribute list_max_attr =
+{
+ .name = "lstmax",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+
+static struct attribute usb_gpio_detect_enable_attr =
+{
+ .name = "gpio_detect",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute *usb_status_attrs[] =
+{
+ &charger_plug_attr,
+ &usb_plug_attr,
+ &sys_id_attr,
+ &en_mods_attr,
+ &ramdump_flag_attr,
+ &net_name_attr,
+ &net0_state_attr,
+ &net1_state_attr,
+ &net2_state_attr,
+ &net3_state_attr,
+ &hotplug_state_attr,
+ &force_net_attr,
+ &set_panic_attr,
+ &list_max_attr,
+ &usb_gpio_detect_enable_attr,
+ NULL,
+};
+
+
+static struct attribute usbprintk_state_attr =
+{
+ .name = "usb",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute mmcprintk_state_attr =
+{
+ .name = "mmc",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute gmacprintk_state_attr =
+{
+ .name = "gmac",
+ .mode = S_IRUGO|S_IWUSR,
+};
+
+static struct attribute *print_status_attrs[] =
+{
+ &usbprintk_state_attr,
+ &mmcprintk_state_attr,
+ &gmacprintk_state_attr,
+ NULL,
+};
+
+
+/***********************************************
+
+ USB MODS
+
+************************************************/
+
+struct usb_mods{
+
+ /* µ¥¹âÅ̱êÖ¾ */
+ int only_cdrom;
+
+ /* ÊÖ¶¯µ¯¹âÅÌ ±êÖ¾*/
+ int is_eject_cdrom;
+
+ /* ×Ô¶¯µ¯¹âÅÌ ±êÖ¾*/
+ int auto_eject_cdrom;
+ int start_timer_flag;
+ struct timer_list timer;
+ struct work_struct work;
+
+ /* ϵͳʶ±ð±êÖ¾ */
+ int sys_id; //0 is windows, other value not windows(mac or linux)
+};
+
+static struct usb_mods mods;
+void usb_mods_activate(void);
+
+/* MODSµ¯¹âÅÌÑÓʱһ°ã·¶Î§Îª3~5Ã룬ÔÝÉèΪ3Ãë */
+#define USB_MODS_TIMER_EXPIRES 3000
+
+
+int usb_do_reject_cdrom(void)
+{
+ if(mods.only_cdrom){
+ USBSTACK_DBG("usb_do_reject_cdrom!!!! ");
+ mods.is_eject_cdrom = 1;
+ }
+ return 1;
+}
+
+int usb_is_reject_cdrom(void)
+{
+ if(mods.is_eject_cdrom){
+ USBSTACK_DBG("usb_is_reject_cdrom!!!! ");
+ usb_notify_up(USB_CDROM_OBJECT, NULL);
+ return 1;
+ }
+
+ usb_mods_activate();
+ return 0;
+}
+void usb_set_sys_id(int sysId)
+{
+ if(sysId){
+ if(mods.sys_id != sysId)
+ USBSTACK_DBG("sys is mac or linux");
+ }else{
+ if(mods.sys_id != sysId)
+ USBSTACK_DBG("sys is windows");
+ }
+ mods.sys_id = sysId;
+}
+
+void usb_set_ms_auto_reject(int flag)
+{
+ if(mods.auto_eject_cdrom == flag)
+ {
+ //USBSTACK_DBG("already set, set mods-eject-cdrom flag: %d", flag);
+ return;
+ }
+
+ if(en_mods){
+ USBSTACK_DBG("mods enable, set mods-eject-cdrom flag: %d", flag);
+ mods.auto_eject_cdrom = flag;
+ }else{
+ USBSTACK_DBG("mods disable, set mods-eject-cdrom flag: 0");
+ mods.auto_eject_cdrom = 0;
+ }
+}
+//EXPORT_SYMBOL_GPL(usb_set_ms_auto_eject);
+
+
+int usb_get_ms_auto_reject(void)
+{
+ if(en_mods)
+ return mods.auto_eject_cdrom;
+ else
+ return 0;
+}
+//EXPORT_SYMBOL_GPL(usb_get_ms_auto_reject);
+
+
+void usb_mods_activate(void)
+{
+ unsigned long expire;
+
+ if(mods.auto_eject_cdrom){
+ //mods.beginTime = jiffies;
+ if(mods.start_timer_flag == 0){
+ expire = msecs_to_jiffies(USB_MODS_TIMER_EXPIRES) + jiffies;
+ mods.start_timer_flag = 1;
+ mod_timer(&mods.timer, expire);
+ USBSTACK_DBG("mods timer start");
+ }
+ }
+}
+
+void usb_mods_deactive(void)
+{
+ mods.start_timer_flag = 0;
+ del_timer_sync(&mods.timer);
+}
+
+void usb_mods_timer_callback(unsigned long data)
+{
+ USBSTACK_DBG("usb mods timer");
+ schedule_work(&mods.work);
+ }
+static void usb_mods_work(struct work_struct *data)
+{
+ USBSTACK_DBG("usb mods work");
+ if(usb_plug)
+ usb_notify_up(USB_CDROM_OBJECT, NULL);
+ }
+
+void usb_mods_init(void)
+{
+ USBSTACK_DBG("usb_mods_init");
+ mods.only_cdrom = 1;
+ mods.auto_eject_cdrom =en_mods;
+ mods.sys_id = 1;
+ mods.start_timer_flag = 0;
+ setup_timer(&mods.timer, usb_mods_timer_callback, (unsigned long)(&mods));
+ INIT_WORK(&mods.work, usb_mods_work);
+}
+
+
+void usb_mods_exit(void)
+{
+ USBSTACK_DBG("usb_mods_exit");
+ usb_mods_deactive();
+ //flush_work_sync(&mods.work);
+ mods.only_cdrom =0;
+ mods.auto_eject_cdrom =0;
+ mods.is_eject_cdrom = 0;
+}
+
+/************usb mods end ****************************/
+unsigned int get_panic_flag(void)
+{
+ return set_panic;
+}
+
+EXPORT_SYMBOL_GPL(get_panic_flag);
+
+unsigned int get_usb_gpio_detect_flag(void)
+{
+ return usb_gpio_detect_enable;
+}
+
+EXPORT_SYMBOL_GPL(get_usb_gpio_detect_flag);
+
+
+int usb_get_rndis_list_max_flag(void)
+{
+ return rndis_vplist_max;
+}
+EXPORT_SYMBOL_GPL(usb_get_rndis_list_max_flag);
+
+
+static void usb_ramdump_config(void)
+{
+ usb_notify_up(USB_RAMDUMP_TRIGGER, NULL);
+}
+ssize_t kobj_usb_show(struct kobject *kobject,struct attribute *attr,char *buf)
+{
+ int dc=0;
+
+ if(!strcmp(attr->name, CHARGER_PLUG_NAME)){
+ sprintf(buf, "%d\n",charger_plug );
+ }else if(!strcmp(attr->name, USB_PLUG_NAME)){
+ dc = detected_charger();
+ USBSTACK_DBG("detected charger=%d",dc);
+ if(dc == 1)
+ usb_plug = 1;
+ sprintf(buf, "%d\n",usb_plug );
+ }else if(!strcmp(attr->name, SYS_ID_NAME)){
+ sprintf(buf, "%d\n",mods.sys_id );
+ }else if(!strcmp(attr->name, ENABLE_MODS)){
+ sprintf(buf, "%d\n",en_mods );
+ }else if(!strcmp(attr->name, RAMDUMP_FLAG)){
+ sprintf(buf, "%d\n",ramdump_flag);
+ }else if(!strcmp(attr->name, NET_NAME)){
+ sprintf(buf,"%s%s%s%s",usblan[0]?"usblan0;":"",usblan[1]?"usblan1;":"",usblan[2]?"usblan2;":"",usblan[3]?"usblan3;":"");
+ }else if(!strcmp(attr->name, NET0_STATE)){
+ sprintf(buf, "%d",usblan[0]);
+ }else if(!strcmp(attr->name, NET1_STATE)){
+ sprintf(buf, "%d",usblan[1]);
+ }else if(!strcmp(attr->name, NET2_STATE)){
+ sprintf(buf, "%d",usblan[2]);
+ }else if(!strcmp(attr->name, NET3_STATE)){
+ sprintf(buf, "%d",usblan[3]);
+ }else if(!strcmp(attr->name, HOT_PLUG)){
+ sprintf(buf, "%d",hotplug_flag);
+ }else if(!strcmp(attr->name, USB_PRINTK_EN)){
+ sprintf(buf, "%d",usb_printk_en);
+ }else if(!strcmp(attr->name, FORCE_NET)){
+ sprintf(buf, "%d",force_net);
+ }else if(!strcmp(attr->name, SET_PANIC)){
+ sprintf(buf, "%u",set_panic);
+ }else if(!strcmp(attr->name, RNDIS_VPLST_MAX)){
+ sprintf(buf, "%u",rndis_vplist_max);
+ } else if(!strcmp(attr->name, USB_GPIO_DETECT_ENABLE)){
+ sprintf(buf, "%u",usb_gpio_detect_enable);
+ }
+
+ return strlen(buf);
+}
+
+//void usbPoll_test(void);
+ssize_t kobj_usb_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)
+{
+ unsigned int value = 0;
+
+ value = simple_strtoul(buf, NULL, 10);
+ if(!strcmp(attr->name,CHARGER_PLUG_NAME)){
+ charger_plug = value;
+ }else if(!strcmp(attr->name,USB_PLUG_NAME)){
+ //usbPoll_test();
+ usb_plug = value;
+ }else if(!strcmp(attr->name,SYS_ID_NAME)){
+ usb_set_sys_id(value);
+ }else if(!strcmp(attr->name,ENABLE_MODS)){
+ en_mods =value;
+ }else if(!strcmp(attr->name,RAMDUMP_FLAG)){
+ ramdump_flag =value;
+ if(ramdump_flag)
+ usb_ramdump_config();
+ }else if(!strcmp(attr->name,NET0_STATE)){
+ usblan[0] =value;
+ }
+ else if(!strcmp(attr->name,NET1_STATE)){
+ usblan[1] =value;
+ }else if(!strcmp(attr->name,NET2_STATE)){
+ usblan[2] =value;
+ }else if(!strcmp(attr->name,NET3_STATE)){
+ usblan[3] =value;
+ }else if(!strcmp(attr->name,HOT_PLUG)){
+ hotplug_flag =value;
+ }else if(!strcmp(attr->name,USB_PRINTK_EN)){
+ usb_printk_en =value;
+ }else if(!strcmp(attr->name,FORCE_NET)){
+ force_net =value;
+ }else if(!strcmp(attr->name,SET_PANIC)){
+ set_panic =value;
+ }else if(!strcmp(attr->name,RNDIS_VPLST_MAX)){
+ rndis_vplist_max =value;
+ }else if(!strcmp(attr->name,USB_GPIO_DETECT_ENABLE)){
+ usb_gpio_detect_enable =value;
+ }
+
+ return size;
+}
+
+static struct sysfs_ops obj_usb_sysops =
+{
+ .show = kobj_usb_show,
+ .store = kobj_usb_store,
+};
+
+void obj_usb_release(struct kobject *kobject)
+{
+ usb_printk("[kobj_test: release!]\n");
+}
+static struct kobj_type ktype =
+
+{ .release = obj_usb_release,
+ .sysfs_ops = &obj_usb_sysops,
+ .default_attrs = usb_status_attrs,
+};
+
+ssize_t kobj_print_show(struct kobject *kobject,struct attribute *attr,char *buf)
+{
+ if(!strcmp(attr->name, USB_PRINTK_EN)){
+ sprintf(buf, "%d",usb_printk_en);
+ }else if(!strcmp(attr->name, MMC_PRINTK_EN)){
+ sprintf(buf, "%d",mmc_printk_en);
+ }else if(!strcmp(attr->name, GMAC_PRINTK_EN)){
+ sprintf(buf, "%d",gmac_printk_en);
+ }
+
+ return strlen(buf);
+}
+
+//void usbPoll_test(void);
+ssize_t kobj_print_store(struct kobject *kobject,struct attribute *attr, const char *buf,size_t size)
+{
+ unsigned int value = 0;
+
+ value = simple_strtoul(buf, NULL, 4);
+ if(!strcmp(attr->name,USB_PRINTK_EN)){
+ usb_printk_en =value;
+ }else if(!strcmp(attr->name,MMC_PRINTK_EN)){
+ mmc_printk_en =value;
+ }else if(!strcmp(attr->name,GMAC_PRINTK_EN)){
+ gmac_printk_en =value;
+ }
+
+ return size;
+}
+
+static struct sysfs_ops obj_print_sysops =
+{
+ .show = kobj_print_show,
+ .store = kobj_print_store,
+};
+static struct kobj_type kprinttype =
+
+{ .release = obj_usb_release,
+ .sysfs_ops = &obj_print_sysops,
+ .default_attrs = print_status_attrs,
+};
+
+static int kset_filter(struct kset *kset,struct kobject *kobj)
+{
+// int ret=0;
+// struct kobj_type *ktype = get_ktype(kobj); /* µÃµ½ÊôÐÔÀàÐÍ */
+// ret = (ktype == &ktype_part);
+ usb_printk("Filter: kobj %s.\n",kobj->name);
+ return 1;
+}
+
+static const char *kset_name(struct kset *kset,struct kobject *kobj)
+{
+ static char buf[20];
+
+/* struct device *dev = to_dev(kobj);
+ if(dev->bus)
+ return dev->bus->name;
+ else if(dev->class)
+ return dev->class->name;
+ else
+*/ {
+ usb_printk("Name kobj %s.\n",kobj->name);
+ sprintf(buf,"%s","dwc_usb");
+ }
+ return buf;
+}
+
+static int kset_uevent(struct kset *kset,struct kobject *kobj, struct kobj_uevent_env *env)
+{
+ int i = 0;
+ usb_printk("uevent: kobj %s.\n",kobj->name);
+
+ while(i < env->envp_idx)
+ {
+ usb_printk("%s.\n",env->envp[i]);
+ i ++;
+ }
+
+ return 0;
+}
+
+static struct kset_uevent_ops uevent_ops =
+{
+ .filter = kset_filter,
+ .name = kset_name,
+ .uevent = kset_uevent,
+};
+
+struct kset *kset_p;
+struct kset *kset_usb;
+//struct kset kset_c;
+struct kobject *usbkobj = NULL;
+struct kobject *printkobj = NULL;
+static int __init kset_usb_init(void)
+{
+ int ret = 0;
+
+ usb_printk("kset test init!\n");
+
+ /* ´´½¨²¢×¢²á kset_p */
+ kset_usb = kset_create_and_add("dwc_usb", &uevent_ops, NULL);
+
+ // kobject_set_name(&kset_c.kobj,"kset_c");
+ // kset_c.kobj.kset = kset_p; /* Ìí¼Ó kset_c µ½ kset_p */
+
+ /* ¶ÔÓÚ½Ïа汾µÄÄںˣ¬ÔÚ×¢²á kset ֮ǰ£¬ÐèÒª
+ * Ìî³ä kset.kobj µÄ ktype ³ÉÔ±£¬·ñÔò×¢²á²»»á³É¹¦ */
+ // kset_c.kobj.ktype = &ktype;
+ //ret = kset_register(&kset_c);
+
+ // if(ret)
+ // kset_unregister(kset_p);
+ usbkobj = kzalloc(sizeof(*usbkobj),GFP_KERNEL);
+ if(!usbkobj){
+ usb_printk(KERN_WARNING "mallock usbkobj failed \n");
+ return 0;
+ }
+ kobject_init(usbkobj, &ktype);
+ kobject_add(usbkobj,&kset_usb->kobj,"%s","usbconfig");
+ usbkobj->kset = kset_usb;
+
+ kset_p = kset_create_and_add("highspeed_print_en", &uevent_ops, NULL);
+
+ printkobj = kzalloc(sizeof(*printkobj),GFP_KERNEL);
+ if(!printkobj){
+ usb_printk(KERN_WARNING "mallock printkobj failed \n");
+ return 0;
+ }
+ kobject_init(printkobj, &kprinttype);
+ kobject_add(printkobj,&kset_p->kobj,"%s","printconfig");
+ printkobj->kset = kset_p;
+
+ // usbkobj = kobject_create_and_add("usbconfig", &kset_p->kobj);
+ // usbkobj->kset = kset_p;
+ //usbkobj->ktype = &ktype;
+
+ return ret;
+}
+
+
+static void __exit kset_usb_exit(void)
+{
+ usb_printk("kset test exit!\n");
+
+ // kset_unregister(&kset_c);
+ kset_unregister(kset_usb);
+ kset_unregister(kset_p);
+}
+
+
+void usb_notify_up(usb_notify_event notify_type, void* puf)
+{
+ unsigned char buf[100];
+ int rtv = -1;
+ enum kobject_action action =KOBJ_MAX;
+ char*envp_ext[] = {NULL,NULL};
+ strcpy(buf, "cdrom-object");
+ switch(notify_type){
+ case USB_CDROM_OBJECT:
+ usb_printk("usb cdrom object \n");
+ USBSTACK_DBG("@CDROM REJECT");
+ strcpy(buf,"USBEVENT=usb_switch");
+ action = KOBJ_CHANGE;
+ break;
+
+ case USB_DEVICE_PLUGIN:
+ usb_printk("usb device plugin \n");
+ USBSTACK_DBG("@USB DEV PLUG IN");
+ strcpy(buf,"USBEVENT=usb_device_in");
+ action = KOBJ_ADD;
+ usb_plug = 1;
+ break;
+
+ case USB_DEVICE_PLUGOUT:
+ usb_printk("usb device plugout \n");
+ USBSTACK_DBG("@USB DEV PLUG OUT");
+ strcpy(buf,"USBEVENT=usb_device_out");
+ action = KOBJ_REMOVE;
+ usb_plug = 0;
+ break;
+ case USB_CHARGER_PLUGIN:
+ usb_printk("usb charger plugin \n");
+ USBSTACK_DBG("@USB CHARGER PLUG IN");
+ strcpy(buf,"USBEVENT=usb_charger_in");
+ action = KOBJ_ADD;
+ charger_plug = 1;
+ break;
+
+ case USB_CHARGER_PLUGOUT:
+ usb_printk("usb charge plugout \n");
+ USBSTACK_DBG("@USB CHARGER PLUG OUT");
+ strcpy(buf,"USBEVENT=usb_charger_out");
+ action = KOBJ_REMOVE;
+ charger_plug = 0;
+ break;
+ case USB_RAMDUMP_TRIGGER:
+ usb_printk("usb ramdump trigger \n");
+ USBSTACK_DBG("@USB RAMDUMP TRIGGERT");
+ strcpy(buf,"USBEVENT=usb_ramdump");
+ action = KOBJ_CHANGE;
+ break;
+ case USB_SWITCH_USER:
+ usb_printk("usb switch to user mode \n");
+ USBSTACK_DBG("@USB SWITCH USER");
+ strcpy(buf,"USBEVENT=usb_user");
+ action = KOBJ_CHANGE;
+ break;
+
+ case USB_SWITCH_DEBUG:
+ usb_printk("usb switch to debug mode \n");
+ USBSTACK_DBG("@USB SWITCH DEBUG");
+ strcpy(buf,"USBEVENT=usb_debug");
+ action = KOBJ_CHANGE;
+ break;
+
+ case USB_SWITCH_FACTORY:
+ usb_printk("usb switch to factory mode \n");
+ USBSTACK_DBG("@USB SWITCH FACTORY");
+ strcpy(buf,"USBEVENT=usb_factory");
+ action = KOBJ_CHANGE;
+ break;
+
+ case USB_SWITCH_AMT:
+ usb_printk("usb switch to amt mode \n");
+ USBSTACK_DBG("@USB SWITCH AMT");
+ strcpy(buf,"USBEVENT=usb_amt");
+ action = KOBJ_CHANGE;
+ break;
+
+ case USB_SWITCH_EYE_DIAGRAM:
+ usb_printk("usb switch to EYE_DIAGRAM mode \n");
+ USBSTACK_DBG("@USB SWITCH EYE_DIAGRAM");
+ strcpy(buf,"USBEVENT=usb_eye_diagram");
+ action = KOBJ_CHANGE;
+ break;
+
+ case USB_DEVICE_EXCEPT_RESET:
+ usb_printk("usb catch except reset \n");
+ USBSTACK_DBG("@USB EXCEPT RESET");
+ strcpy(buf,"USBEVENT=usb_except_reset");
+ action = KOBJ_CHANGE;
+ break;
+
+ default:
+ usb_printk(KERN_WARNING "UNKWON USB EVENT \n");
+ break;
+ }
+ envp_ext[0] = buf;
+ if(usbkobj && hotplug_flag){
+ rtv = kobject_uevent_env(usbkobj, action,envp_ext);
+ }
+ usb_printk(KERN_WARNING "rtv:%d \n",rtv);
+}
+EXPORT_SYMBOL_GPL(usb_notify_up);
+
+
+
+void usb_dbg_printf(const char *fmt,...)
+{
+ va_list args;
+ int stringCnt = 0;
+
+ if ((USB_LOG_MAX_SIZE +s_usbMemLogIndex)>=USB_LOG_MEM_SIZE)
+ {
+ s_usbMemLogIndex=0;
+ }
+
+ s_localStringBuf = &s_usbMemLog[s_usbMemLogIndex];
+
+
+ va_start(args, fmt);
+ stringCnt+=vsprintf((char *)s_localStringBuf, fmt, args);
+ va_end(args);
+
+ s_usbMemLogIndex+=stringCnt;
+}
+EXPORT_SYMBOL_GPL(usb_dbg_printf);
+
+void usb_dbg_showLog(void)
+{
+ int SingleStrLen=0;
+ char logBuf[USB_LOG_MAX_SIZE+1]={0};
+ char *pStart=s_usbMemLog;
+ char *pEnd=NULL;
+
+ logBuf[USB_LOG_MAX_SIZE] = '\n';
+
+ pEnd = (char *)strchr((const char *)pStart, '\n');
+ while((pEnd < (&s_usbMemLog[USB_LOG_MEM_SIZE]))&&(pEnd >=pStart))
+ {
+ SingleStrLen= pEnd-pStart;
+ memcpy(logBuf,pStart,SingleStrLen);
+ printk("%s\n", logBuf);
+
+ do{
+ pStart=pEnd?(pEnd+1):(pStart+1);
+ memset(logBuf,0,USB_LOG_MAX_SIZE);
+ pEnd = (char *)strchr((const char *)pStart, '\n');
+ }while(!pEnd);
+ }
+
+}
+EXPORT_SYMBOL_GPL(usb_dbg_showLog);
+
+void usb_dbg_ep0reg(void)
+{
+#if 0
+ USBREG_DBG("\n GINTSTS: 0x%08x, GINTMASK: 0x%08x, DCFG: 0x%08x, DCTL: 0x%08x,\n DSTS: 0x%08x, DIEPMSK: 0x%08x, DOEPMSK: 0x%08x, DAINT: 0x%08x,\n DAINTMSK: 0x%08x, DIEPCTL0: 0x%08x, DIEPINT0: 0x%08x, DIEPTSIZE0:0x%08x,\n DIEPDMA0: 0x%08x, DIEPDMB0: 0x%08x, DOEPCTL0: 0x%08x, DOEPINT0: 0x%08x,\n DOEPSIZ0: 0x%08x, DOEPDMA0: 0x%08x, unused: 0x%08x, DOEPDMAB0:0x%08x,",
+ *(volatile unsigned int *)(ZX_USB_BASE+0x14), //GINTSTS
+ *(volatile unsigned int *)(ZX_USB_BASE+0x18), //GINTMAK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x800), //DCFG
+ *(volatile unsigned int *)(ZX_USB_BASE+0x804), //DCTL line1 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0x808), //DSTS
+ *(volatile unsigned int *)(ZX_USB_BASE+0x810), //DIEPMSK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x814), //DOEPMSK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x818), //DAINT line2 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0x81c), //DAINTMSK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x900), //DIEPCTL0
+ *(volatile unsigned int *)(ZX_USB_BASE+0x908), //DIEPINT0
+ *(volatile unsigned int *)(ZX_USB_BASE+0x910), //DIEPTSIZE0 line3 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0x914), //DIEPDMA0
+ *(volatile unsigned int *)(ZX_USB_BASE+0x91C), //DIEPDMB0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB00), //DOEPCTL0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB08), //DOEPINT0 line4 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB10), //DOEPSIZ0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB14), //DOEPDMA0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB18), //unused
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB1C) //DOEPDMAB0 line5 end
+ );
+#endif
+}
+EXPORT_SYMBOL_GPL(usb_dbg_ep0reg);
+
+void usb_print_ep0reg(void)
+{
+ USBHAL_DBG("\n GINTSTS: 0x%08x, GINTMASK: 0x%08x, DCFG: 0x%08x, DCTL: 0x%08x,\n DSTS: 0x%08x, DIEPMSK: 0x%08x, DOEPMSK: 0x%08x, DAINT: 0x%08x,\n DAINTMSK: 0x%08x, DIEPCTL0: 0x%08x, DIEPINT0: 0x%08x, DIEPTSIZE0:0x%08x,\n DIEPDMA0: 0x%08x, DIEPDMB0: 0x%08x, DOEPCTL0: 0x%08x, DOEPINT0: 0x%08x,\n DOEPSIZ0: 0x%08x, DOEPDMA0: 0x%08x, unused: 0x%08x, DOEPDMAB0:0x%08x,",
+ *(volatile unsigned int *)(ZX_USB_BASE+0x14), //GINTSTS
+ *(volatile unsigned int *)(ZX_USB_BASE+0x18), //GINTMAK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x800), //DCFG
+ *(volatile unsigned int *)(ZX_USB_BASE+0x804), //DCTL line1 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0x808), //DSTS
+ *(volatile unsigned int *)(ZX_USB_BASE+0x810), //DIEPMSK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x814), //DOEPMSK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x818), //DAINT line2 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0x81c), //DAINTMSK
+ *(volatile unsigned int *)(ZX_USB_BASE+0x900), //DIEPCTL0
+ *(volatile unsigned int *)(ZX_USB_BASE+0x908), //DIEPINT0
+ *(volatile unsigned int *)(ZX_USB_BASE+0x910), //DIEPTSIZE0 line3 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0x914), //DIEPDMA0
+ *(volatile unsigned int *)(ZX_USB_BASE+0x91C), //DIEPDMB0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB00), //DOEPCTL0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB08), //DOEPINT0 line4 end
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB10), //DOEPSIZ0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB14), //DOEPDMA0
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB18), //unused
+ *(volatile unsigned int *)(ZX_USB_BASE+0xB1C) //DOEPDMAB0 line5 end
+ );
+}
+EXPORT_SYMBOL_GPL(usb_print_ep0reg);
+module_init(kset_usb_init);
+
+module_exit(kset_usb_exit);
+
+