/* ******************************************************************************* * sw_ehci_hcd_shutdown * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ void sw_ehci_hcd_shutdown(struct platform_device* pdev) { struct sw_hci_hcd *sw_ehci = NULL; if(pdev == NULL){ DMSG_PANIC("ERR: Argment is invalid\n"); return; } sw_ehci = pdev->dev.platform_data; if(sw_ehci == NULL){ DMSG_PANIC("ERR: sw_ehci is null\n"); return; } if(sw_ehci->probe == 0){ DMSG_PANIC("ERR: sw_ehci is disable, need not shutdown\n"); return; } DMSG_INFO("[%s]: ehci shutdown start\n", sw_ehci->hci_name); usb_hcd_platform_shutdown(pdev); sw_stop_ehci(sw_ehci); DMSG_INFO("[%s]: ehci shutdown end\n", sw_ehci->hci_name); return ; }
/* ******************************************************************************* * get_usb_cfg * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static s32 get_usb_cfg(struct sw_hci_hcd *sw_hci) { __s32 ret = 0; /* usbc enable */ ret = script_parser_fetch(usbc_name[sw_hci->usbc_no], "usb_used", (int *)&sw_hci->used, 64); if(ret != 0) { DMSG_PANIC("ERR: get usbc2 enable failed\n"); //return -1; } /* request gpio */ ret = script_parser_fetch(usbc_name[sw_hci->usbc_no], "usb_drv_vbus_gpio", (int *)&sw_hci->drv_vbus_gpio_set, 64); if(ret != 0) { DMSG_PANIC("ERR: get usbc%d(%s) id failed\n", sw_hci->usbc_no, usbc_name[sw_hci->usbc_no]); return -1; } /* host_init_state */ ret = script_parser_fetch(usbc_name[sw_hci->usbc_no], "usb_host_init_state", (int *)&(sw_hci->host_init_state), 64); if(ret != 0) { DMSG_PANIC("ERR: script_parser_fetch host_init_state failed\n"); return -1; } return 0; }
/* ******************************************************************************* * clock_init * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static s32 clock_init(struct sw_hci_hcd *sw_hci, u32 ohci) { if(ohci){ /* ohci */ sw_hci->sie_clk = clk_get(NULL, "ahb_ohci0"); if (IS_ERR(sw_hci->sie_clk)){ DMSG_PANIC("ERR: get ohci%d abh clk failed.\n", (sw_hci->usbc_no - 1)); goto failed; } sw_hci->ohci_gate = clk_get(NULL, "usb_ohci0"); if (IS_ERR(sw_hci->ohci_gate)){ DMSG_PANIC("ERR: get ohci%d gate clk failed.\n", (sw_hci->usbc_no - 1)); goto failed; } }else{ /* ehci */ sw_hci->sie_clk = clk_get(NULL, "ahb_ehci0"); if (IS_ERR(sw_hci->sie_clk)){ DMSG_PANIC("ERR: get ehci%d abh clk failed.\n", (sw_hci->usbc_no - 1)); goto failed; } } sw_hci->phy_gate = clk_get(NULL, "usb_phy1"); if (IS_ERR(sw_hci->phy_gate)){ DMSG_PANIC("ERR: get usb%d phy_gate failed.\n", sw_hci->usbc_no); goto failed; } sw_hci->phy_reset = clk_get(NULL, "usb_phy1"); if (IS_ERR(sw_hci->phy_reset)){ DMSG_PANIC("ERR: get usb%d phy_reset failed.\n", sw_hci->usbc_no); goto failed; } return 0; failed: if(sw_hci->sie_clk){ clk_put(sw_hci->sie_clk); sw_hci->sie_clk = NULL; } if(sw_hci->phy_gate){ clk_put(sw_hci->phy_gate); sw_hci->phy_gate = NULL; } if(sw_hci->phy_reset){ clk_put(sw_hci->phy_reset); sw_hci->phy_reset = NULL; } if(sw_hci->ohci_gate){ clk_put(sw_hci->ohci_gate); sw_hci->ohci_gate = NULL; } return -1; }
/* ******************************************************************************* * 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; }
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 ; }
/* ******************************************************************************* * sw_hci_sun5i_exit * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static void __exit sw_hci_sun5i_exit(void) { #ifdef CONFIG_USB_SW_SUN5I_EHCI0 if(sw_ehci0.used){ platform_device_unregister(&sw_usb_ehci_device[0]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ehci0.usbc_no, sw_ehci0.hci_name); } #endif #ifdef CONFIG_USB_SW_SUN5I_OHCI0 if(sw_ohci0.used){ platform_device_unregister(&sw_usb_ohci_device[0]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ohci0.usbc_no, sw_ohci0.hci_name); } #endif #ifdef CONFIG_USB_SW_SUN5I_EHCI1 if(sw_ehci1.used){ platform_device_unregister(&sw_usb_ehci_device[1]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ehci1.usbc_no, sw_ehci1.hci_name); } #endif #ifdef CONFIG_USB_SW_SUN5I_OHCI1 if(sw_ohci1.used){ platform_device_unregister(&sw_usb_ohci_device[1]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ohci1.usbc_no, sw_ohci1.hci_name); } #endif /* USB1 */ exit_sw_hci(&sw_ehci0, 0); exit_sw_hci(&sw_ohci0, 1); free_pin(usb1_drv_vbus_Handle); usb1_drv_vbus_Handle = 0; /* USB2 */ exit_sw_hci(&sw_ehci1, 0); exit_sw_hci(&sw_ohci1, 1); free_pin(usb2_drv_vbus_Handle); usb2_drv_vbus_Handle = 0; 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; }
/* ******************************************************************************* * sw_ehci_hcd_suspend * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int sw_ehci_hcd_suspend(struct device *dev) { struct sw_hci_hcd *sw_ehci = NULL; struct usb_hcd *hcd = NULL; struct ehci_hcd *ehci = NULL; unsigned long flags = 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_ehci = dev->platform_data; if(sw_ehci == NULL){ DMSG_PANIC("ERR: sw_ehci is null\n"); return 0; } if(sw_ehci->probe == 0){ DMSG_PANIC("ERR: sw_ehci is disable, can not suspend\n"); return 0; } ehci = hcd_to_ehci(hcd); if(ehci == NULL){ DMSG_PANIC("ERR: ehci is null\n"); return 0; } DMSG_INFO("[%s]: sw_ehci_hcd_suspend\n", sw_ehci->hci_name); spin_lock_irqsave(&ehci->lock, flags); ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev)); ehci_writel(ehci, 0, &ehci->regs->intr_enable); (void)ehci_readl(ehci, &ehci->regs->intr_enable); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); spin_unlock_irqrestore(&ehci->lock, flags); sw_stop_ehci(sw_ehci); return 0; }
/* ******************************************************************************* * check_usb_board_info * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static __s32 check_usb_board_info(struct usb_cfg *cfg) { //------------------------------------- // USB0 //------------------------------------- if(cfg->port[0].enable){ /* 检查port的使用类型是否合法 */ if(cfg->port[0].port_type != USB_PORT_TYPE_DEVICE && cfg->port[0].port_type != USB_PORT_TYPE_HOST && cfg->port[0].port_type != USB_PORT_TYPE_OTG){ DMSG_PANIC("ERR: usbc0 port_type(%d) is unkown\n", cfg->port[0].port_type); goto err; } /* 检查USB的插拔检测方式是否合法 */ if(cfg->port[0].detect_type != USB_DETECT_TYPE_DP_DM && cfg->port[0].detect_type != USB_DETECT_TYPE_VBUS_ID){ DMSG_PANIC("ERR: usbc0 detect_type(%d) is unkown\n", cfg->port[0].detect_type); goto err; } /* 如果用VBUS/ID检测方式,就必须检查id/vbus pin 的有效性 */ if(cfg->port[0].detect_type == USB_DETECT_TYPE_VBUS_ID){ if(cfg->port[0].id.valid == 0){ DMSG_PANIC("ERR: id pin is invaild\n"); goto err; } if(cfg->port[0].det_vbus.valid == 0){ DMSG_PANIC("ERR: det_vbus pin is invaild\n"); goto err; } } } //------------------------------------- // USB1 //------------------------------------- //------------------------------------- // USB2 //------------------------------------- return 0; err: return -1; }
/* ******************************************************************************* * 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; }
/* ******************************************************************************* * ShowPictureEx * * Description: * 把图片数据解析到指定的地址中,并且显示出来. * 如果指定的地址为NULL, 则可以存放在任何地址。 * * Parameters: * Para : input. Boot阶段的参数。 * Path : input. 图片存放在介质中的位置,如“c:\logo.bmp” * Addr : input. 存放解析后的图片, * * Return value: * 0 : 成功 * !0 : 失败 * * note: * void * ******************************************************************************* */ __u32 ShowPictureEx(char *Path, __u32 address) { Picture_t PictureInfo; __s32 ret = 0; display_layer_info_t *layer_para = NULL; /* 参数初始化 */ if(!board_res.layer_hd) { return 0; } memset(&PictureInfo, 0, sizeof(Picture_t)); ret = Parse_Pic_BMP_ByPath(Path, &PictureInfo, address); if(ret != 0) { DMSG_PANIC("ERR: Parse_Pic_BMP failed\n"); goto error; } /* 显示图片 */ layer_para = ui_AllocLayerPara(&PictureInfo); ShowLayer(board_res.layer_hd, layer_para, board_res.display_source); #ifndef SPEED_UP_BOOT wBoot_timer_delay(50); #endif return (__u32)layer_para; error: return 0; }
static void hci_port_configure(struct sw_hci_hcd *sw_hci, u32 enable) { unsigned long reg_value = 0; u32 usbc_sdram_hpcr = 0; void __iomem *addr = NULL; if (sw_hci->usbc_no == 1) { usbc_sdram_hpcr = SW_SDRAM_REG_HPCR_USB1; } else if (sw_hci->usbc_no == 2) { usbc_sdram_hpcr = SW_SDRAM_REG_HPCR_USB2; } else { DMSG_PANIC("EER: unkown usbc_no(%d)\n", sw_hci->usbc_no); return; } addr = (void __iomem*) SW_VA_DRAM_IO_BASE + usbc_sdram_hpcr; reg_value = readl(addr); if (enable) reg_value |= BIT(SW_SDRAM_BP_HPCR_ACCESS_EN); else reg_value &= ~BIT(SW_SDRAM_BP_HPCR_ACCESS_EN); writel(reg_value, addr); 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; }
/* ******************************************************************************* * 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; }
int sunxi_usb_enable_hcd(__u32 usbc_no) { #ifndef SUNXI_USB_FPGA if (usbc_no == 0) { #ifndef CONFIG_ARCH_SUN9IW1 #if defined(CONFIG_USB_SUNXI_USB0_OTG) || defined(USB_SUNXI_USB0_HOST_ONLY) sunxi_usb_enable_hcd0(); #endif #endif } else if (usbc_no == 1) { #if defined(CONFIG_USB_SUNXI_EHCI0) sunxi_usb_enable_ehci(usbc_no); #endif #if defined(CONFIG_USB_SUNXI_OHCI0) sunxi_usb_enable_ohci(usbc_no); #endif } else if (usbc_no == 2) { #if defined(CONFIG_USB_SUNXI_EHCI1) sunxi_usb_enable_ehci(usbc_no); #endif #if defined(CONFIG_USB_SUNXI_OHCI1) sunxi_usb_enable_ohci(usbc_no); #endif } else { DMSG_PANIC("ERR: unkown usbc_no(%d)\n", usbc_no); return -1; } #endif return 0; }
/* ******************************************************************************* * usbc0_platform_device_init * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ __s32 usbc0_platform_device_init(struct usb_port_info *port_info) { /* device */ sw_udc_cfg.port_info = port_info; sw_udc_cfg.usbc_base = SW_VA_USB0_IO_BASE; /* host */ sw_hcd_config.port_info = port_info; switch(port_info->port_type){ case USB_PORT_TYPE_DEVICE: platform_device_register(&sw_udc_device); break; case USB_PORT_TYPE_HOST: platform_device_register(&sw_hcd_device); break; case USB_PORT_TYPE_OTG: platform_device_register(&sw_udc_device); platform_device_register(&sw_hcd_device); break; default: DMSG_PANIC("ERR: unkown port_type(%d)\n", port_info->port_type); } return 0; }
int xhci_scan_init(void) { init_completion(&xhci_complete_notify); init_completion(&xhci_thread_started); usb_connect_flag = 0; no_device_flag = 1; xhci_scan_thread_run = 1; xhci_scan_thread_exit = 0; atomic_set(&xhci_thread_suspend_flag, 0); xhci_th = kthread_create(xhci_scan_thread, NULL, "xhci-scan"); if (IS_ERR(xhci_th)) { DMSG_PANIC("ERR: kthread_create xhci_scan_thread failed\n"); return -1; } xhci_enable = 1; wake_up_process(xhci_th); wait_for_completion(&xhci_thread_started); return 0; }
__s32 usbc0_platform_device_exit(struct usb_port_info *info) { #ifndef CONFIG_ARCH_SUN9IW1 switch(info->port_type) { case USB_PORT_TYPE_DEVICE: platform_device_unregister(&sunxi_udc_device); break; case USB_PORT_TYPE_HOST: platform_device_unregister(&sunxi_hcd_device); break; case USB_PORT_TYPE_OTG: platform_device_unregister(&sunxi_udc_device); #if !defined (CONFIG_ARCH_SUN8IW8) && !defined (CONFIG_ARCH_SUN8IW7) platform_device_unregister(&sunxi_hcd_device); #endif break; default: DMSG_PANIC("ERR: unkown port_type(%d)\n", info->port_type); } #else platform_device_unregister(&sunxi_otg); #endif return 0; }
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 }
/* ******************************************************************************* * usb_msg_center * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ void usb_msg_center(struct usb_cfg *cfg) { enum usb_role role = USB_ROLE_NULL; struct usb_msg_center_info * center_info = &g_center_info; /* receive massage */ print_usb_msg(center_info); modify_msg(¢er_info->msg); /* execute cmd */ role = get_usb_role(); DMSG_DBG_MANAGER("role=%d\n", get_usb_role()); switch(role){ case USB_ROLE_NULL: do_usb_role_null(center_info); break; case USB_ROLE_HOST: do_usb_role_host(center_info); break; case USB_ROLE_DEVICE: do_usb_role_device(center_info); break; default: DMSG_PANIC("ERR: unkown role(%x)\n", role); } return; }
/* ******************************************************************************* * sw_usb_enable_hcd * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ int sw_usb_enable_hcd(__u32 usbc_no) { if(usbc_no == 0){ #if defined(CONFIG_USB_SW_SUN4I_USB0_OTG) || defined(USB_SW_SUN4I_USB0_HOST_ONLY) sw_usb_enable_hcd0(); #endif }else if(usbc_no == 1){ #if defined(CONFIG_USB_SW_SUN4I_EHCI0) sw_usb_enable_ehci(usbc_no); #endif #if defined(CONFIG_USB_SW_SUN4I_OHCI0) sw_usb_enable_ohci(usbc_no); #endif }else if(usbc_no == 2){ #if defined(CONFIG_USB_SW_SUN4I_EHCI1) sw_usb_enable_ehci(usbc_no); #endif #if defined(CONFIG_USB_SW_SUN4I_OHCI1) sw_usb_enable_ohci(usbc_no); #endif }else{ DMSG_PANIC("ERR: unkown usbc_no(%d)\n", usbc_no); return -1; } return 0; }
static int sunxi_ohci_hcd_remove(struct platform_device *pdev) { struct usb_hcd *hcd = NULL; struct sunxi_hci_hcd *sunxi_ohci = NULL; if(pdev == NULL){ DMSG_PANIC("ERR: Argment is invalid\n"); return -1; } hcd = platform_get_drvdata(pdev); if(hcd == NULL){ DMSG_PANIC("ERR: hcd is null\n"); return -1; } sunxi_ohci = pdev->dev.platform_data; if(sunxi_ohci == NULL){ DMSG_PANIC("ERR: sunxi_ohci is null\n"); return -1; } DMSG_INFO("[%s%d]: remove, pdev->name: %s, pdev->id: %d, sunxi_ohci: 0x%p\n", ohci_name, sunxi_ohci->usbc_no, pdev->name, pdev->id, sunxi_ohci); if(sunxi_ohci->not_suspend){ scene_lock_destroy(&ohci_standby_lock[sunxi_ohci->usbc_no]); } usb_remove_hcd(hcd); sunxi_stop_ohc(sunxi_ohci); sunxi_ohci->probe = 0; usb_put_hcd(hcd); sunxi_release_io_resource(pdev, sunxi_ohci); sunxi_ohci->hcd = NULL; if(sunxi_ohci->host_init_state){ g_sunxi_ohci[sunxi_ohci->usbc_no] = NULL; } platform_set_drvdata(pdev, NULL); return 0; }
/* ******************************************************************************* * sw_hci_sun4i_init * * Description: * void * * Parameters: * void * * Return value: * void * * note: * void * ******************************************************************************* */ static int __init sw_hci_sun4i_init(void) { printk("[%s %d]\n", __func__, __LINE__); /* USB1 */ init_sw_hci(&sw_ehci0, 1, 0, ehci_name); init_sw_hci(&sw_ohci0, 1, 1, ohci_name); alloc_pin(&sw_ehci0); /* USB2 */ init_sw_hci(&sw_ehci1, 2, 0, ehci_name); init_sw_hci(&sw_ohci1, 2, 1, ohci_name); alloc_pin(&sw_ehci1); #ifdef CONFIG_USB_SW_SUN7I_EHCI0 if(sw_ehci0.used){ platform_device_register(&sw_usb_ehci_device[0]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ehci0.usbc_no, sw_ehci0.hci_name); } #endif #ifdef CONFIG_USB_SW_SUN7I_OHCI0 if(sw_ohci0.used){ platform_device_register(&sw_usb_ohci_device[0]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ohci0.usbc_no, sw_ohci0.hci_name); } #endif #ifdef CONFIG_USB_SW_SUN7I_EHCI1 if(sw_ehci1.used){ platform_device_register(&sw_usb_ehci_device[1]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ehci1.usbc_no, sw_ehci1.hci_name); } #endif #ifdef CONFIG_USB_SW_SUN7I_OHCI1 if(sw_ohci1.used){ platform_device_register(&sw_usb_ohci_device[1]); }else{ DMSG_PANIC("ERR: usb%d %s is disable\n", sw_ohci1.usbc_no, sw_ohci1.hci_name); } #endif return 0; }
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); scene_unlock(&ohci_standby_lock[sunxi_ohci->usbc_no]); disable_wakeup_src(CPUS_USBMOUSE_SRC, 0); }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; }
static int init_sunxi_hci(struct sunxi_hci_hcd *sunxi_hci, u32 usbc_no, u32 ohci, const char *hci_name) { s32 ret = 0; memset(sunxi_hci, 0, sizeof(struct sunxi_hci_hcd)); sunxi_hci->usbc_no = usbc_no; sunxi_hci->usbc_type = ohci ? SUNXI_USB_OHCI : SUNXI_USB_EHCI; if(ohci){ sunxi_hci->irq_no = ohci_irq_no[sunxi_hci->usbc_no]; }else{ sunxi_hci->irq_no = ehci_irq_no[sunxi_hci->usbc_no]; } sprintf(sunxi_hci->hci_name, "%s%d", hci_name, sunxi_hci->usbc_no); sunxi_hci->usb_vbase = (void __iomem *)usbc_base[sunxi_hci->usbc_no]; sunxi_hci->sram_vbase = (void __iomem *)SUNXI_SRAMCTRL_VBASE; sunxi_hci->clock_vbase = (void __iomem *)SUNXI_CCM_VBASE; sunxi_hci->gpio_vbase = (void __iomem *)SUNXI_PIO_VBASE; sunxi_hci->sdram_vbase = (void __iomem *)SUNXI_SDMMC1_VBASE; get_usb_cfg(sunxi_hci); request_usb_regulator_io(sunxi_hci); sunxi_hci->open_clock = open_clock; sunxi_hci->close_clock = close_clock; sunxi_hci->set_power = sunxi_set_vbus; sunxi_hci->usb_passby = usb_passby; sunxi_hci->port_configure = hci_port_configure; #ifdef CONFIG_USB_SUNXI_HSIC u32 reg_value = 0; reg_value = USBC_Readl(sunxi_hci->sram_vbase+ SUNXI_USB_PMU_IRQ_ENABLE); reg_value |= (1 << 1); reg_value |= (1 << 20); reg_value |= (1 << 17); USBC_Writel(reg_value, (sunxi_hci->sram_vbase+ SUNXI_USB_PMU_IRQ_ENABLE)); #endif #ifndef CONFIG_ARCH_SUN9IW1 #ifdef SUNXI_USB_FPGA fpga_config_use_hci((__u32 __force)sunxi_hci->sram_vbase); #endif #endif ret = clock_init(sunxi_hci, ohci); if(ret != 0){ DMSG_PANIC("ERR: clock_init failed\n"); goto failed1; } print_sunxi_hci(sunxi_hci); return 0; failed1: return -1; }
static s32 request_usb_regulator_io(struct sunxi_otgc *otgc) { if(otgc->port_ctl.regulator_io != NULL){ otgc->port_ctl.regulator_io_hdle = regulator_get(NULL, otgc->port_ctl.regulator_io); if(IS_ERR(otgc->port_ctl.regulator_io_hdle)) { DMSG_PANIC("ERR: some error happen, usb0 regulator_io_hdle fail to get regulator!\n"); return 0; } if(regulator_set_voltage(otgc->port_ctl.regulator_io_hdle , otgc->port_ctl.regulator_value, otgc->port_ctl.regulator_value) < 0 ){ DMSG_PANIC("ERR: usb0 regulator_set_voltage is fail\n"); regulator_put(otgc->port_ctl.regulator_io_hdle); return 0; } } return 0; }
static void sw_usb_3g_config(struct sw_hci_hcd *sw_hci) { script_item_value_type_e type = 0; script_item_u item_temp; u32 usb_3g_used = 0; u32 usb_3g_usbc_num = 0; u32 usb_3g_usbc_type = 0; /* 3g_used */ type = script_get_item("3g_para", "3g_used", &item_temp); if(type == SCIRPT_ITEM_VALUE_TYPE_INT){ usb_3g_used = item_temp.val; }else{ DMSG_PANIC("ERR: script_parser_fetch usb_3g_used failed\n"); usb_3g_used = 0; } if(usb_3g_used){ /* 3g_usbc_num */ type = script_get_item("3g_para", "3g_usbc_num", &item_temp); if(type == SCIRPT_ITEM_VALUE_TYPE_INT){ usb_3g_usbc_num = item_temp.val; }else{ DMSG_PANIC("ERR: script_parser_fetch usb_3g_usbc_num failed\n"); usb_3g_usbc_num = 0; } /* 3g_usbc_type */ type = script_get_item("3g_para", "3g_usbc_type", &item_temp); if(type == SCIRPT_ITEM_VALUE_TYPE_INT){ usb_3g_usbc_type = item_temp.val; }else{ DMSG_PANIC("ERR: script_parser_fetch usb_3g_usbc_type failed\n"); usb_3g_usbc_type = 0; } /* 只开3G使用的那个模组 */ if(sw_hci->usbc_no == usb_3g_usbc_num){ sw_hci->used = 0; if(sw_hci->usbc_type == usb_3g_usbc_type){ sw_hci->used = 1; } } } }