static void __sunxi_set_vbus(struct sunxi_hci_hcd *sunxi_hci, int is_on) { u32 on_off = 0; DMSG_INFO("[%s]: Set USB Power %s\n", sunxi_hci->hci_name, (is_on ? "ON" : "OFF")); /* set power flag */ sunxi_hci->power_flag = is_on; /* set power */ if(sunxi_hci->drv_vbus_gpio_set.gpio.data == 0){ on_off = is_on ? 1 : 0; }else{ on_off = is_on ? 0 : 1; } if(sunxi_hci->drv_vbus_gpio_valid){ if((sunxi_hci->regulator_io != NULL) && (sunxi_hci->regulator_io_hdle != NULL)){ if(on_off){ if(regulator_enable(sunxi_hci->regulator_io_hdle) < 0){ DMSG_INFO("ERR: %s: regulator_enable fail\n", sunxi_hci->hci_name); } }else{ if(regulator_disable(sunxi_hci->regulator_io_hdle) < 0){ DMSG_INFO("ERR: %s: regulator_disable fail\n", sunxi_hci->hci_name); } } } __gpio_set_value(sunxi_hci->drv_vbus_gpio_set.gpio.gpio, on_off); } return; }
/* ******************************************************************************* * usb_manager_exit * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static void __exit usb_manager_exit(void) { bsp_usbc_t usbc; DMSG_DBG_MANAGER("[sw usb]: usb_manager_exit\n"); #if defined(CONFIG_USB_SW_SUN3I_USB0_DEVICE_ONLY) DMSG_INFO("CONFIG_USB_SW_SUN3I_USB0_DEVICE_ONLY\n"); #elif defined(CONFIG_USB_SW_SUN3I_USB0_HOST_ONLY) DMSG_INFO("CONFIG_USB_SW_SUN3I_USB0_HOST_ONLY\n"); #elif defined(CONFIG_USB_SW_SUN3I_USB0_OTG) DMSG_INFO("CONFIG_USB_SW_SUN3I_USB0_OTG\n"); #else DMSG_INFO("CONFIG_USB_SW_SUN3I_USB0_NULL\n"); return; #endif memset(&usbc, 0, sizeof(bsp_usbc_t)); USBC_exit(&usbc); #ifdef CONFIG_USB_SW_SUN3I_USB0_OTG thread_run_flag = 0; while(!thread_stopped_flag){ DMSG_INFO("waitting for usb_hardware_scan_thread stop\n"); } usb_hw_scan_exit(&g_usb_cfg); #endif usbc0_platform_device_exit(); usbc1_platform_device_exit(); usbc2_platform_device_exit(); return; }
static int close_clock(struct sunxi_hci_hcd *sunxi_hci, u32 ohci) { DMSG_INFO("[%s]: close clock, is_open: %d\n", sunxi_hci->hci_name, sunxi_hci->clk_is_open); #ifdef CONFIG_ARCH_SUN9IW1 usb_hci_clock_cnt --; if(usb_hci_clock_cnt == 0 && (hci_ahb_gate != NULL)){ DMSG_INFO("clk_disable_unprepare: hci_ahb_gate\n"); clk_disable_unprepare(hci_ahb_gate); } if(sunxi_hci->clk_is_open){ sunxi_hci->clk_is_open = 0; close_hci_clock(sunxi_hci,ohci); } #ifdef CONFIG_USB_SUNXI_HSIC if(regulator_disable(vbat_hsic_hdle) < 0){ DMSG_INFO("ERR: vbat_hsic: regulator_disable fail\n"); return 0; } #else if(regulator_disable(vbat_usbh_hdle) < 0){ DMSG_INFO("ERR: vbat_usbh: regulator_disable fail\n"); return 0; } #endif return 0; #else if(sunxi_hci->ahb && sunxi_hci->mod_usbphy && sunxi_hci->clk_is_open){ sunxi_hci->clk_is_open = 0; #ifdef CONFIG_USB_SUNXI_HSIC { u32 reg_value = 0; u32 i = 0; u32 ccmu_base = (u32)SUNXI_CCM_VBASE; reg_value = USBC_Readl(ccmu_base + 0xcc); reg_value &= ~ (0x01<<10); reg_value &= ~ (0x01<<11); USBC_Writel(reg_value, (ccmu_base + 0xcc)); for(i=0; i < 0x100; i++); reg_value &= ~ (0x01 << 2); USBC_Writel(reg_value, (ccmu_base + 0xcc)); } #else clk_disable_unprepare(sunxi_hci->mod_usbphy); #endif clk_disable_unprepare(sunxi_hci->ahb); mdelay(10); }else{ DMSG_PANIC("[%s]: wrn: open clock failed, (0x%p, 0x%p, %d, 0x%p)\n", sunxi_hci->hci_name,sunxi_hci->ahb, sunxi_hci->mod_usbphy, sunxi_hci->clk_is_open, sunxi_hci->mod_usb); } return 0; #endif }
/* ******************************************************************************* * open_usb_clock * * Description: * * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static s32 sunxi_open_usb_clock(struct sunxi_otgc *otgc) { DMSG_INFO("start: %s\n", __func__); otgc->port_ctl.otg_clk = clk_get(NULL, USBOTG_CLK); if (IS_ERR(otgc->port_ctl.otg_clk)){ DMSG_PANIC("ERR: OPEN otg_clk failed.\n"); } if(clk_prepare_enable(otgc->port_ctl.otg_clk)){ DMSG_PANIC("ERR:try otg_clk to prepare_enable failed!\n" ); } otgc->port_ctl.otg_phyclk = clk_get(NULL, "usbotgphy"); if (IS_ERR(otgc->port_ctl.otg_phyclk)){ DMSG_PANIC("ERR: OPEN otg_phyclk failed.\n"); } if(clk_prepare_enable(otgc->port_ctl.otg_phyclk)){ DMSG_PANIC("ERR:try otg_phyclk to prepare_enable failed!\n" ); } sunxi_otgc_open_phy(otgc->regs); udelay(10); DMSG_INFO("end: %s\n", __func__); return 0; }
/* ******************************************************************************* * sw_ohci_hcd_shutdown * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ void sw_ohci_hcd_shutdown(struct platform_device* pdev) { struct sw_hci_hcd *sw_ohci = NULL; sw_ohci = pdev->dev.platform_data; if(sw_ohci == NULL){ DMSG_PANIC("ERR: sw_ohci is null\n"); return ; } if(sw_ohci->probe == 0){ DMSG_PANIC("ERR: sw_ohci is disable, need not shutdown\n"); return ; } DMSG_INFO("[%s]: ohci shutdown start\n", sw_ohci->hci_name); usb_hcd_platform_shutdown(pdev); sw_stop_ohc(sw_ohci); DMSG_INFO("[%s]: ohci shutdown end\n", sw_ohci->hci_name); return; }
/* ******************************************************************************* * close_usb_clock * * Description: * * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static s32 sunxi_close_usb_clock(struct sunxi_otgc *otgc) { DMSG_INFO("start: %s\n", __func__); sunxi_otgc_close_phy(otgc->regs); if(otgc->port_ctl.otg_clk != NULL){ clk_disable_unprepare(otgc->port_ctl.otg_clk); } if(!IS_ERR(otgc->port_ctl.otg_clk)){ clk_put(otgc->port_ctl.otg_clk); otgc->port_ctl.otg_clk = NULL; } if(otgc->port_ctl.otg_phyclk != NULL){ clk_disable_unprepare(otgc->port_ctl.otg_phyclk); } if(!IS_ERR(otgc->port_ctl.otg_phyclk)){ clk_put(otgc->port_ctl.otg_phyclk); otgc->port_ctl.otg_phyclk = NULL; } DMSG_INFO("end: %s\n", __func__); return 0; }
static void sunxi_ohci_hcd_shutdown(struct platform_device* pdev) { struct sunxi_hci_hcd *sunxi_ohci = NULL; sunxi_ohci = pdev->dev.platform_data; if(sunxi_ohci == NULL){ DMSG_PANIC("ERR: sunxi_ohci is null\n"); return ; } if(sunxi_ohci->probe == 0){ DMSG_PANIC("ERR: sunxi_ohci is disable, need not shutdown\n"); return ; } DMSG_INFO("[%s]: ohci shutdown start\n", sunxi_ohci->hci_name); if(sunxi_ohci->not_suspend){ scene_lock_destroy(&ohci_standby_lock[sunxi_ohci->usbc_no]); } usb_hcd_platform_shutdown(pdev); sunxi_stop_ohc(sunxi_ohci); DMSG_INFO("[%s]: ohci shutdown end\n", sunxi_ohci->hci_name); return; }
static int sunxi_ohci_hcd_resume(struct device *dev) { struct sunxi_hci_hcd *sunxi_ohci = NULL; struct usb_hcd *hcd = NULL; if(dev == NULL){ DMSG_PANIC("ERR: Argment is invalid\n"); return 0; } hcd = dev_get_drvdata(dev); if(hcd == NULL){ DMSG_PANIC("ERR: hcd is null\n"); return 0; } sunxi_ohci = dev->platform_data; if(sunxi_ohci == NULL){ DMSG_PANIC("ERR: sunxi_ohci is null\n"); return 0; } if(sunxi_ohci->probe == 0){ DMSG_PANIC("ERR: sunxi_ohci is disable, can not resume\n"); return 0; } if(sunxi_ohci->not_suspend){ DMSG_INFO("[%s]: controller not suspend, need not resume\n", sunxi_ohci->hci_name); #if defined (CONFIG_ARCH_SUN8IW6) || defined (CONFIG_ARCH_SUN9IW1) sunxi_ohci->hci_phy_ctrl(sunxi_ohci, 1); #endif scene_unlock(&ohci_standby_lock[sunxi_ohci->usbc_no]); disable_wakeup_src(CPUS_USBMOUSE_SRC, 0); #ifdef CONFIG_USB_HCD_ENHANCE if(sunxi_ohci->usbc_no == 1){ atomic_set(&hci1_thread_scan_flag, 1); } if(sunxi_ohci->usbc_no == 3){ atomic_set(&hci3_thread_scan_flag, 1); } #endif }else{ DMSG_INFO("[%s]: sunxi_ohci_hcd_resume\n", sunxi_ohci->hci_name); #ifndef CONFIG_ARCH_SUN9IW1 #ifdef SUNXI_USB_FPGA fpga_config_use_hci((__u32 __force)sunxi_ohci->sram_vbase); #endif #endif sunxi_start_ohci(sunxi_ohci); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); ohci_finish_controller_resume(hcd); } return 0; }
/* ******************************************************************************* * print_all_usb_reg * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ void print_all_usb_reg(spinlock_t *lock, __u32 usbc_base, __s32 ep_start, __u32 ep_end, char *str) { __u32 i = 0; __u32 old_ep_index = 0; unsigned long flags = 0; if(lock){ spin_lock_irqsave(lock, flags); } DMSG_INFO("\n"); DMSG_INFO("-------------------print_all_usb_reg: %s----------------\n", str); old_ep_index = USBC_Readw(usbc_base + USBC_REG_o_EPIND); for(i = ep_start; i <= ep_end; i++){ print_usb_reg_by_ep(lock, usbc_base, i, str); } USBC_Writew(old_ep_index, (usbc_base + USBC_REG_o_EPIND)); DMSG_INFO("---------------------------------------------------------------------------\n"); DMSG_INFO("\n"); if(lock){ spin_unlock_irqrestore(lock, flags); } return; }
static int sunxi_otg_resume(struct device *dev) { struct platform_device *pdev = NULL; struct sunxi_otgc *otgc = NULL; int ret; pdev = sunxi_otg_pdev; if(pdev == NULL){ DMSG_PANIC("%s, pdev is NULL\n", __func__); return 0; } otgc = platform_get_drvdata(pdev); if(otgc == NULL){ DMSG_PANIC("%s, otgc is NULL\n", __func__); return 0; } DMSG_INFO("start:%s, otgc_work_mode:%d\n", __func__, otgc_work_mode); if(otgc_work_mode == 0){ DMSG_INFO("end:%s, otgc driver is no work and no need resume\n", __func__); atomic_set(&thread_suspend_flag, 0); goto end; } sunxi_open_usb_clock(otgc); sunxi_set_mode(otgc, otgc_work_mode); switch(otgc_work_mode){ case SUNXI_GCTL_PRTCAP_HOST: sunxi_core_soft_reset(otgc->regs); sunxi_host_set_vbus(otgc, 1); break; case SUNXI_GCTL_PRTCAP_DEVICE: ret = sunxi_core_init(otgc); if (ret) { dev_err(&pdev->dev, "failed to initialize core, %s_%d\n", __func__, __LINE__); atomic_set(&thread_suspend_flag, 0); return ret; } sunxi_gadget_resume(otgc); atomic_set(&thread_suspend_flag, 0); break; default: return 0; } end: pm_runtime_disable(&pdev->dev); pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); DMSG_INFO("end: %s\n", __func__); return 0; }
/* ******************************************************************************* * sw_hcd_port_suspend * * Description: * suspend USB port * * Parameters: * sw_hcd : input. USB¿ØÖÆÆ÷ * do_suspend : input. flag. is suspend USB port or not? * * Return value: * void * * note: * void * ******************************************************************************* */ static void sw_hcd_port_suspend(struct sw_hcd *sw_hcd, bool do_suspend) { u8 power = 0; void __iomem *usbc_base = sw_hcd->mregs; if (!is_host_active(sw_hcd)){ DMSG_PANIC("ERR: usb host is not active\n"); return; } /* NOTE: this doesn't necessarily put PHY into low power mode, * turning off its clock; that's a function of PHY integration and * sw_hcd_POWER_ENSUSPEND. PHY may need a clock (sigh) to detect * SE0 changing to connect (J) or wakeup (K) states. */ power = USBC_Readb(USBC_REG_PCTL(usbc_base)); if (do_suspend) { int retries = 10000; DMSG_INFO("[sw_hcd]: suspend port.\n"); power &= ~(1 << USBC_BP_POWER_H_RESUME); power |= (1 << USBC_BP_POWER_H_SUSPEND); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); /* Needed for OPT A tests */ power = USBC_Readb(USBC_REG_PCTL(usbc_base)); while (power & (1 << USBC_BP_POWER_H_SUSPEND)) { power = USBC_Readb(USBC_REG_PCTL(usbc_base)); if (retries-- < 1) break; } DMSG_DBG_HCD("DBG: Root port suspended, power %02x\n", power); sw_hcd->port1_status |= USB_PORT_STAT_SUSPEND; }else if (power & (1 << USBC_BP_POWER_H_SUSPEND)){ DMSG_INFO("[sw_hcd]: suspend portend, resume port.\n"); power &= ~(1 << USBC_BP_POWER_H_SUSPEND); power |= (1 << USBC_BP_POWER_H_RESUME); USBC_Writeb(power, USBC_REG_PCTL(usbc_base)); DMSG_DBG_HCD("DBG: Root port resuming, power %02x\n", power); /* later, GetPortStatus will stop RESUME signaling */ sw_hcd->port1_status |= SW_HCD_PORT_STAT_RESUME; sw_hcd->rh_timer = jiffies + msecs_to_jiffies(20); }else{ DMSG_PANIC("WRN: sw_hcd_port_suspend nothing to do\n"); } return ; }
static int sunxi_pin_init(struct sunxi_otgc *otgc) { int ret = 0; script_item_value_type_e type = 0; script_item_u item_temp; /* usbc drv_vbus */ type = script_get_item("usbc0", "usb_drv_vbus_gpio", &(otgc->port_ctl.drv_vbus.gpio_set)); if (type == SCIRPT_ITEM_VALUE_TYPE_PIO) { otgc->port_ctl.drv_vbus.valid = 1; } else { otgc->port_ctl.drv_vbus.valid = 0; DMSG_PANIC("ERR: get usbc det_vbus failed\n"); } if (otgc->port_ctl.drv_vbus.valid) { ret = gpio_request(otgc->port_ctl.drv_vbus.gpio_set.gpio.gpio, "otg_drv_vbus"); if (ret != 0) { DMSG_PANIC("ERR: gpio_request failed\n"); otgc->port_ctl.drv_vbus.valid = 0; } else { gpio_direction_output(otgc->port_ctl.drv_vbus.gpio_set.gpio.gpio, 0); } } /* get regulator io information */ type = script_get_item("usbc0", "usb_regulator_io", &item_temp); if (type == SCIRPT_ITEM_VALUE_TYPE_STR) { if (!strcmp(item_temp.str, "nocare")) { DMSG_INFO("get usbc0_regulator is nocare\n"); otgc->port_ctl.regulator_io = NULL; }else{ otgc->port_ctl.regulator_io = item_temp.str; type = script_get_item("usbc0", "usb_regulator_vol", &item_temp); if(type == SCIRPT_ITEM_VALUE_TYPE_INT){ otgc->port_ctl.regulator_value = item_temp.val; }else{ DMSG_INFO("get usbc0_value is failed\n"); otgc->port_ctl.regulator_value = 0; } } }else { DMSG_INFO("get usbc0_regulator is failed\n"); otgc->port_ctl.regulator_io = NULL; } return 0; }
static void insmod_host_driver(struct usb_msg_center_info *center_info) { DMSG_INFO("\n\ninsmod_host_driver\n\n"); set_usb_role(center_info, USB_ROLE_HOST); sunxi_usb_host0_enable(); #if 1 DMSG_INFO("FORCED USB Charge\n\n"); axp_usbcur(CHARGE_USB_30); axp_usbvol(CHARGE_USB_30); #endif return; }
/* ******************************************************************************* * do_usb_req_set_address * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int do_usb_req_set_address(void) { set_address = 1; udc.address = (u8) (udc.req.wValue & 0x7f); udc.speed = USBC_Dev_QueryTransferMode(udc.bsp); udc.bulk_ep_size = fastboot_is_highspeed() ? HIGH_SPEED_EP_MAX_PACKET_SIZE : FULL_SPEED_EP_MAX_PACKET_SIZE; udc.fifo_size = BULK_FIFOSIZE; DMSG_INFO("address:%d, speed:%d, bulk_ep_size:%d, fifo_size:%d\n", udc.address, udc.speed, udc.bulk_ep_size, udc.fifo_size); DMSG_INFO("usb enter %s\n", (udc.speed == USB_SPEED_HIGH) ? "high speed" : "full speed"); return FASTBOOT_OK; }
/* ******************************************************************************* * fastboot_bulk_endpoint_reset * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static void fastboot_bulk_endpoint_reset (void) { u8 old_ep_index = 0; DMSG_INFO("fastboot_bulk_endpoint_reset\n"); old_ep_index = USBC_GetActiveEp(udc.bsp); print_sw_udc(&udc); /* tx */ USBC_SelectActiveEp(udc.bsp, BULK_IN_EP_INDEX); USBC_Dev_ConfigEp(udc.bsp, USBC_TS_TYPE_BULK, USBC_EP_TYPE_TX, 1, udc.bulk_ep_size & 0x7ff); USBC_ConfigFifo(udc.bsp, USBC_EP_TYPE_TX, 1, udc.fifo_size, 1024); //1k开始, 每个ep分配1K的空间 USBC_INT_EnableEp(udc.bsp, USBC_EP_TYPE_TX, BULK_IN_EP_INDEX); /* rx */ USBC_SelectActiveEp(udc.bsp, BULK_OUT_EP_INDEX); USBC_Dev_ConfigEp(udc.bsp, USBC_TS_TYPE_BULK, USBC_EP_TYPE_RX, 1, udc.bulk_ep_size & 0x7ff); USBC_ConfigFifo(udc.bsp, USBC_EP_TYPE_RX, 1, udc.fifo_size, 2048); //2k开始, 每个ep分配1K的空间 USBC_INT_EnableEp(udc.bsp, USBC_EP_TYPE_RX, BULK_OUT_EP_INDEX); USBC_SelectActiveEp(udc.bsp, old_ep_index); return; }
static int close_clock(struct sw_hci_hcd *sw_hci, u32 ohci) { DMSG_INFO("[%s]: close clock\n", sw_hci->hci_name); if (sw_hci->sie_clk && sw_hci->phy_gate && sw_hci->phy_reset && sw_hci->clk_is_open) { sw_hci->clk_is_open = 0; if (ohci && sw_hci->ohci_gate) clk_disable(sw_hci->ohci_gate); clk_reset(sw_hci->phy_reset, 1); clk_disable(sw_hci->phy_reset); clk_disable(sw_hci->phy_gate); clk_disable(sw_hci->sie_clk); } else { DMSG_PANIC ("[%s]: wrn: open clock failed, (0x%p, 0x%p, 0x%p, %d, 0x%p)\n", sw_hci->hci_name, sw_hci->sie_clk, sw_hci->phy_gate, sw_hci->phy_reset, sw_hci->clk_is_open, sw_hci->ohci_gate); } dbg_clocks(sw_hci); return 0; }
static int open_clock(struct sw_hci_hcd *sw_hci, u32 ohci) { DMSG_INFO("[%s]: open clock\n", sw_hci->hci_name); if (sw_hci->sie_clk && sw_hci->phy_gate && sw_hci->phy_reset && !sw_hci->clk_is_open) { sw_hci->clk_is_open = 1; clk_enable(sw_hci->phy_gate); clk_enable(sw_hci->phy_reset); clk_reset(sw_hci->phy_reset, 0); if (ohci && sw_hci->ohci_gate) clk_enable(sw_hci->ohci_gate); mdelay(10); clk_enable(sw_hci->sie_clk); mdelay(10); UsbPhyInit(sw_hci->usbc_no); } else { DMSG_PANIC ("[%s]: wrn: open clock failed, (0x%p, 0x%p, 0x%p, %d, 0x%p)\n", sw_hci->hci_name, sw_hci->sie_clk, sw_hci->phy_gate, sw_hci->phy_reset, sw_hci->clk_is_open, sw_hci->ohci_gate); } dbg_clocks(sw_hci); return 0; }
static void rmmod_host_driver(struct usb_msg_center_info *center_info) { DMSG_INFO("\n\nrmmod_host_driver\n\n"); #if defined (CONFIG_ARCH_SUN8IW8) || defined (CONFIG_ARCH_SUN8IW7) #if defined(CONFIG_USB_SUNXI_EHCI0) sunxi_usb_disable_ehci(0); #endif #if defined(CONFIG_USB_SUNXI_OHCI0) sunxi_usb_disable_ohci(0); #endif #else { int ret = 0; ret = sunxi_usb_host0_disable(); if (ret != 0) { DMSG_PANIC("err: disable hcd0 failed\n"); return; } } #endif set_usb_role(center_info, USB_ROLE_NULL); return; }
int sunxi_usb_disable_ohci(__u32 usbc_no) { struct sunxi_hci_hcd *sunxi_ohci = NULL; if(usbc_no != 1 && usbc_no != 2){ DMSG_PANIC("ERR:Argmen invalid. usbc_no(%d)\n", usbc_no); return -1; } sunxi_ohci = g_sunxi_ohci[usbc_no]; if(sunxi_ohci == NULL){ DMSG_PANIC("ERR: sunxi_ohci is null\n"); return -1; } if(sunxi_ohci->host_init_state){ DMSG_PANIC("ERR: not support sunxi_usb_disable_ohci\n"); return -1; } if(sunxi_ohci->probe == 0){ DMSG_PANIC("ERR: sunxi_ohci is disable, can not disable again\n"); return -1; } sunxi_ohci->probe = 0; DMSG_INFO("[%s]: sunxi_usb_disable_ohci\n", sunxi_ohci->hci_name); sunxi_ohci_hcd_remove(sunxi_ohci->pdev); return 0; }
int sunxi_usb_disable_ohci(__u32 usbc_no) { struct sunxi_hci_hcd *sunxi_ohci = NULL; sunxi_ohci = g_sunxi_ohci[usbc_no]; if(sunxi_ohci == NULL){ DMSG_PANIC("ERR: sunxi_ohci is null\n"); return -1; } #if !defined (CONFIG_ARCH_SUN8IW8) && !defined (CONFIG_ARCH_SUN8IW7) && !defined (CONFIG_USB_HCD_ENHANCE) if(sunxi_ohci->host_init_state){ DMSG_PANIC("ERR: not support sunxi_usb_disable_ohci\n"); return -1; } #endif if(sunxi_ohci->probe == 0){ DMSG_PANIC("ERR: sunxi_ohci is disable, can not disable again\n"); return -1; } sunxi_ohci->probe = 0; DMSG_INFO("[%s]: sunxi_usb_disable_ohci\n", sunxi_ohci->hci_name); sunxi_ohci_hcd_remove(sunxi_ohci->pdev); return 0; }
/* ******************************************************************************* * close_clock * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int close_clock(struct sw_hci_hcd *sw_hci, u32 ohci) { DMSG_INFO("[%s]: close clock\n", sw_hci->hci_name); if(sw_hci->sie_clk && sw_hci->phy_gate && sw_hci->phy_reset && sw_hci->clk_is_open){ sw_hci->clk_is_open = 0; if(ohci && sw_hci->ohci_gate){ clk_disable(sw_hci->ohci_gate); } clk_reset(sw_hci->phy_reset, 1); clk_disable(sw_hci->phy_reset); clk_disable(sw_hci->phy_gate); clk_disable(sw_hci->sie_clk); }else{ DMSG_PANIC("[%s]: wrn: open clock failed, (0x%p, 0x%p, 0x%p, %d, 0x%p)\n", sw_hci->hci_name, sw_hci->sie_clk, sw_hci->phy_gate, sw_hci->phy_reset, sw_hci->clk_is_open, sw_hci->ohci_gate); } DMSG_DEBUG("[%s]: close clock, 0x60(0x%x), 0xcc(0x%x)\n", sw_hci->hci_name, (u32)USBC_Readl(SW_VA_CCM_IO_BASE + 0x60), (u32)USBC_Readl(SW_VA_CCM_IO_BASE + 0xcc)); return 0; }
/* ******************************************************************************* * open_usb_clock * * Description: * * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ u32 open_usb_clock(sw_udc_io_t *sw_udc_io) { DMSG_INFO_UDC("open_usb_clock\n"); if(sw_udc_io->sie_clk && sw_udc_io->phy_clk && sw_udc_io->phy0_clk && !sw_udc_io->clk_is_open){ clk_enable(sw_udc_io->sie_clk); mdelay(10); clk_enable(sw_udc_io->phy_clk); clk_enable(sw_udc_io->phy0_clk); clk_reset(sw_udc_io->phy0_clk, 0); mdelay(10); sw_udc_io->clk_is_open = 1; }else{ DMSG_PANIC("ERR: clock handle is null, sie_clk(0x%p), phy_clk(0x%p), phy0_clk(0x%p), open(%d)\n", sw_udc_io->sie_clk, sw_udc_io->phy_clk, sw_udc_io->phy0_clk, sw_udc_io->clk_is_open); } UsbPhyInit(0); #if 0 DMSG_INFO("[udc0]: open, 0x60(0x%x), 0xcc(0x%x)\n", (u32)USBC_Readl(SW_VA_CCM_IO_BASE + 0x60), (u32)USBC_Readl(SW_VA_CCM_IO_BASE + 0xcc)); #endif return 0; }
int sunxi_usb_device_disable(void) { struct platform_device *pdev = NULL; struct sunxi_otgc *otgc = NULL; pdev = sunxi_otg_pdev; if(pdev == NULL){ DMSG_PANIC("%s, pdev is NULL\n", __func__); return 0; } otgc = platform_get_drvdata(pdev); if(otgc == NULL){ DMSG_PANIC("%s, otgc is NULL\n", __func__); return 0; } sunxi_gadget_disable(otgc); sunxi_set_mode(otgc, 0); sunxi_core_exit(otgc); sunxi_close_usb_clock(otgc); DMSG_INFO("otgc_work_mode:%d\n", otgc_work_mode); return 0; }
int sunxi_usb_device_enable(void) { struct platform_device *pdev = NULL; struct sunxi_otgc *otgc = NULL; int ret = 0; pdev = sunxi_otg_pdev; if(pdev == NULL){ DMSG_PANIC("%s, pdev is NULL\n", __func__); return 0; } otgc = platform_get_drvdata(pdev); if(otgc == NULL){ DMSG_PANIC("%s, otgc is NULL\n", __func__); return 0; } sunxi_open_usb_clock(otgc); ret = sunxi_core_init(otgc); if (ret) { dev_err(&pdev->dev, "wangjx failed to initialize core, %s_%d\n", __func__, __LINE__); return ret; } sunxi_set_mode(otgc, SUNXI_GCTL_PRTCAP_DEVICE); sunxi_gadget_enable(otgc); DMSG_INFO("otgc_work_mode:%d\n", otgc_work_mode); return 0; }
/* ******************************************************************************* * sw_usb_enable_ohci * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ int sw_usb_enable_ohci(__u32 usbc_no) { struct sw_hci_hcd *sw_ohci = NULL; if(usbc_no != 1 && usbc_no != 2){ DMSG_PANIC("ERR:Argmen invalid. usbc_no(%d)\n", usbc_no); return -1; } sw_ohci = g_sw_ohci[usbc_no]; if(sw_ohci == NULL){ DMSG_PANIC("ERR: sw_ohci is null\n"); return -1; } if(sw_ohci->host_init_state){ DMSG_PANIC("ERR: not support sw_usb_enable_ohci\n"); return -1; } if(sw_ohci->probe == 1){ DMSG_PANIC("ERR: sw_ohci is already enable, can not enable again\n"); return -1; } sw_ohci->probe = 1; DMSG_INFO("[%s]: sw_usb_enable_ohci\n", sw_ohci->hci_name); sw_ohci_hcd_probe(sw_ohci->pdev); return 0; }
void sunxi_set_mode(struct sunxi_otgc *otgc, u32 mode) { char * name; sunxi_set_mode_ex(otgc->regs, mode); switch(mode){ case SUNXI_GCTL_PRTCAP_HOST: name = "host"; break; case SUNXI_GCTL_PRTCAP_DEVICE: name = "device"; break; default: name = "NULL"; break; } otgc->mode = mode; otgc_work_mode = mode; DMSG_INFO("sunxi_controller_mode:%s!\n", name); return; }
/* ******************************************************************************* * sw_ohci_hcd_suspend * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int sw_ohci_hcd_suspend(struct device *dev) { struct sw_hci_hcd *sw_ohci = NULL; struct usb_hcd *hcd = NULL; struct ohci_hcd *ohci = NULL; unsigned long flags = 0; int rc = 0; if(dev == NULL){ DMSG_PANIC("ERR: Argment is invalid\n"); return 0; } hcd = dev_get_drvdata(dev); if(hcd == NULL){ DMSG_PANIC("ERR: hcd is null\n"); return 0; } sw_ohci = dev->platform_data; if(sw_ohci == NULL){ DMSG_PANIC("ERR: sw_ohci is null\n"); return 0; } if(sw_ohci->probe == 0){ DMSG_PANIC("ERR: sw_ohci is disable, can not suspend\n"); return 0; } ohci = hcd_to_ohci(hcd); if(ohci == NULL){ DMSG_PANIC("ERR: ohci is null\n"); return 0; } DMSG_INFO("[%s]: sw_ohci_hcd_suspend\n", sw_ohci->hci_name); /* Root hub was already suspended. Disable irq emission and * mark HW unaccessible, bail out if RH has been resumed. Use * the spinlock to properly synchronize with possible pending * RH suspend or resume activity. * * This is still racy as hcd->state is manipulated outside of * any locks =P But that will be a different fix. */ spin_lock_irqsave(&ohci->lock, flags); ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); (void)ohci_readl(ohci, &ohci->regs->intrdisable); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irqrestore(&ohci->lock, flags); sw_stop_ohc(sw_ohci); return rc; }
/* ******************************************************************************* * insmod_host_driver * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static void insmod_host_driver(struct usb_msg_center_info *center_info) { DMSG_INFO("\n\ninsmod_host_driver\n\n"); set_usb_role(center_info, USB_ROLE_HOST); sw_usb_host0_enable(); return; }
static void insmod_device_driver(struct usb_msg_center_info *center_info) { DMSG_INFO("\n\ninsmod_device_driver\n\n"); set_usb_role(center_info, USB_ROLE_DEVICE); sw_usb_device_enable(); return; }
/* ******************************************************************************* * rmmod_device_driver * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static void rmmod_device_driver(struct usb_msg_center_info *center_info) { DMSG_INFO("\n\nrmmod_device_driver\n\n"); set_usb_role(center_info, USB_ROLE_NULL); sw_usb_device_disable(); return; }