/* * Unregister entry point for the peripheral controller driver. */ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) { struct s3c_udc *dev = the_controller; unsigned long flags; if (!dev) return -ENODEV; if (!driver || driver != dev->driver) return -EINVAL; disable_irq(IRQ_OTG); spin_lock_irqsave(&dev->lock, flags); s3c_udc_stop_activity(dev, driver); spin_unlock_irqrestore(&dev->lock, flags); driver->unbind(&dev->gadget); device_del(&dev->gadget.dev); DEBUG_SETUP("Unregistered gadget driver '%s'\n", driver->driver.name); #ifndef CONFIG_PM s3c_udc_disable(dev); #endif dev->gadget.dev.driver = NULL; dev->driver = NULL; dev->config_gadget_driver = NO_GADGET_DRIVER; return 0; }
/* * power down s3c-udc power & disable otg clock */ void s3c_udc_power_down(void) { struct s3c_udc *dev = the_controller; unsigned long flags; /* Confirm No caller with spin_lock come here */ if (dev->udc_state != USB_STATE_SUSPENDED && dev->gadget.speed != USB_SPEED_UNKNOWN ) { //s3c_udc_set_disconnect_state(dev); S3C_UDC_LOCK_IRQSAVE(&dev->lock, flags); s3c_udc_stop_activity(dev, dev->driver); S3C_UDC_UNLOCK_IRQRESTORE(&dev->lock, flags); } if(dev->udc_state > USB_STATE_NOTATTACHED) { /* s3c_udc_disable() set dev->udc_state = USB_STATE_NOTATTACHED; */ s3c_udc_disable(dev); S3C_UDC_POWER_OFF: if(dev->clocked) { if (!IS_ERR(otg_clock) && otg_clock != NULL) { clk_disable(otg_clock); dev->clocked = 0; DEBUG_PM("[%s] clk_disable() OK.\n", __func__); } else DEBUG_ERROR("[%s] otg_clock error\n", __func__); } else DEBUG_PM("[%s] already clk_disabled\n", __func__); fsa9480_s3c_udc_off(); if(dev->clocked) { /* Just in case */ DEBUG_ERROR("\n[%s] readl(S3C_UDC_OTG_GINTMSK) || dev->clocked\n", __func__); DEBUG_ERROR("\n[%s] Power OFF again.\n", __func__); goto S3C_UDC_POWER_OFF; } DEBUG_PM("[%s] \n", __func__); } else { DEBUG_PM("[%s] skipped , already powered off\n", __func__); if(dev->clocked) { /* Just in case */ DEBUG_ERROR("\n[%s] readl(S3C_UDC_OTG_GINTMSK) || dev->clocked\n", __func__); DEBUG_ERROR("\n[%s] Power OFF again.\n", __func__); goto S3C_UDC_POWER_OFF; } } dev->powered = 0; #ifdef CONFIG_CPU_FREQ set_dvfs_level(1); #endif /* CONFIG_CPU_FREQ */ }
static int s3c_udc_suspend(struct platform_device *pdev, pm_message_t state) { struct s3c_udc *dev = platform_get_drvdata(pdev); unsigned long flags; DEBUG_PM("[%s]: System Suspend \n", __func__); #if NO_USING_USB_SWITCH DEBUG_PM("[%s]: NO_USING_USB_SWITCH just return\n", __func__); return 0; #endif spin_lock_irqsave(&dev->lock, flags); //save the state of connection to udc_resume_state dev->udc_resume_state = dev->udc_state; dev->udc_resume_speed = dev->gadget.speed; if (dev->gadget.speed != USB_SPEED_UNKNOWN) { DEBUG_PM("[%s]: USB enumerated at suspend\n", __func__); //s3c_udc_soft_disconnect(); s3c_udc_stop_activity(dev, dev->driver); } else { DEBUG_PM("[%s] USB not enumerated at suspend\n", __func__); DEBUG_PM("[%s] dev->powered [%d] at suspend\n", __func__, dev->powered); if (dev->powered == 0) { DEBUG_PM("[%s] skip~~ s3c_udc_power_down() at suspend\n", __func__); spin_unlock_irqrestore(&dev->lock, flags); return 0; } } switch(pm_policy) { case ALL_POWER_DOWN: // s3c_udc_stop_activity(dev, dev->driver); //confirm clk disable s3c_udc_power_down(); break; case CLOCK_GATING: s3c_udc_suspend_clock_gating(); break; case OPHYPWR_FORCE_SUSPEND: writel((readl(S3C_USBOTG_PHYPWR)|(1<<FORCE_SUSPEND)), S3C_USBOTG_PHYPWR); break; default: DEBUG_ERROR("[%s]: not proper pm_policy\n", __func__); } spin_unlock_irqrestore(&dev->lock, flags); return 0; }
/* * power down s3c-udc power & disable otg clock */ void s3c_udc_power_down(void) { struct s3c_udc *dev = the_controller; /* Confirm */ if (dev->udc_state != USB_STATE_SUSPENDED) { //s3c_udc_set_disconnect_state(dev); s3c_udc_stop_activity(dev, dev->driver); } if(dev->udc_state > USB_STATE_NOTATTACHED) { /* s3c_udc_disable() set dev->udc_state = USB_STATE_NOTATTACHED; */ s3c_udc_disable(dev); S3C_UDC_POWER_OFF: if(dev->clocked) { if (!IS_ERR(otg_clock) && otg_clock != NULL) { clk_disable(otg_clock); dev->clocked = 0; DEBUG_PM("[%s] clk_disable() OK.\n", __func__); } else DEBUG_ERROR("[%s] otg_clock error\n", __func__); } else DEBUG_PM("[%s] already clk_disabled\n", __func__); fsa9480_s3c_udc_off(); if(dev->clocked) { /* Just in case */ DEBUG_ERROR("\n[%s] readl(S3C_UDC_OTG_GINTMSK) || dev->clocked\n", __func__); DEBUG_ERROR("\n[%s] Power OFF again.\n", __func__); goto S3C_UDC_POWER_OFF; } DEBUG_PM("[%s] \n", __func__); } else { DEBUG_PM("[%s] skipped , already powered off\n", __func__); if(dev->clocked) { /* Just in case */ DEBUG_ERROR("\n[%s] readl(S3C_UDC_OTG_GINTMSK) || dev->clocked\n", __func__); DEBUG_ERROR("\n[%s] Power OFF again.\n", __func__); goto S3C_UDC_POWER_OFF; } } dev->powered = 0; }
/* * usb_gadget_ops pullup */ static int s3c_udc_pullup(struct usb_gadget *gadget, int is_on) { //#ifdef CONFIG_PM #if 0 //logical if (is_on) { s3c_udc_soft_connect(); } else { s3c_udc_soft_disconnect(); } #else struct s3c_udc *dev = the_controller; unsigned long flags; //UDC power on/off if (is_on) { DEBUG_PM("[%s] is_on[%d]\n", __func__, is_on); /* * if early s3c_udc_power_up make * fsa9480_check_usb_connection failed to detect USB connection */ #if NO_USING_USB_SWITCH s3c_udc_power_up(); #else fsa9480_check_usb_connection(); #endif } else { DEBUG_PM("[%s] is_on[%d]\n", __func__, is_on); S3C_UDC_LOCK_IRQSAVE(&dev->lock, flags); s3c_udc_stop_activity(dev, dev->driver); s3c_udc_power_down(); S3C_UDC_UNLOCK_IRQRESTORE(&dev->lock, flags); } #endif return 0; }