/* * OHCI HCD (Host Controller Driver) for USB. * * (C) Copyright 1999 Roman Weissgaerber * (C) Copyright 2000-2002 David Brownell * (C) Copyright 2002 Hewlett-Packard Company * * USB Bus Glue for Samsung S3C2410 * * Written by Christopher Hoover * Based on fragments of previous driver by Rusell King et al. * * Modified for S3C2410 from ohci-sa1111.c, ohci-omap.c and ohci-lh7a40.c * by Ben Dooks, * Copyright (C) 2004 Simtec Electronics * * Thanks to basprog@mail.ru for updates to newer kernels * * This file is licenced under the GPL. */ #include #include #include #include #include #include //Qisda, Leo SJ Yang, 2009/08/31, for 3G power #if defined(CONFIG_CPU_S3C6400) #include #elif defined(CONFIG_CPU_S3C6410) #include #endif #define USB_HOST_PORT2_EN 0 /*Qisda,Leo SJ Yang,2009/09/09{*/ /*Fix 3G Module can not work after running mass storage*/ #ifdef CONFIG_USB_GADGET extern char g_EMUSBTestIsOK; #endif /*}Qisda,Leo SJ Yang,2009/09/09*/ /*Fix 3G Module can not work after running mass storage*/ #if (USB_HOST_PORT2_EN == 1) && (CONFIG_PLAT_S3C64XX == 1) #include #endif #define valid_port(idx) ((idx) == 1 || (idx) == 2) /* clock device associated with the hcd */ static struct clk *clk; static struct clk *usb_clk; #if (USB_HOST_PORT2_EN == 1) && (CONFIG_PLAT_S3C64XX == 1) static struct clk *otg_clk; #endif /* forward definitions */ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc); /* conversion functions */ static struct s3c2410_hcd_info *to_s3c2410_info(struct usb_hcd *hcd) { return hcd->self.controller->platform_data; } static void s3c2410_start_hc(struct platform_device *dev, struct usb_hcd *hcd) { struct s3c2410_hcd_info *info = dev->dev.platform_data; dev_dbg(&dev->dev, "s3c2410_start_hc:\n"); clk_enable(usb_clk); mdelay(2); /* let the bus clock stabilise */ clk_enable(clk); #if (USB_HOST_PORT2_EN == 1) && (CONFIG_PLAT_S3C64XX == 1) clk_enable(otg_clk); #endif if (info != NULL) { info->hcd = hcd; info->report_oc = s3c2410_hcd_oc; if (info->enable_oc != NULL) { (info->enable_oc)(info, 1); } } } static void s3c2410_stop_hc(struct platform_device *dev) { struct s3c2410_hcd_info *info = dev->dev.platform_data; dev_dbg(&dev->dev, "s3c2410_stop_hc:\n"); if (info != NULL) { info->report_oc = NULL; info->hcd = NULL; if (info->enable_oc != NULL) { (info->enable_oc)(info, 0); } } clk_disable(clk); clk_disable(usb_clk); } /* ohci_s3c2410_hub_status_data * * update the status data from the hub with anything that * has been detected by our system */ static int ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf) { struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); struct s3c2410_hcd_port *port; int orig; int portno; orig = ohci_hub_status_data (hcd, buf); if (info == NULL) return orig; port = &info->port[0]; /* mark any changed port as changed */ for (portno = 0; portno < 2; port++, portno++) { if (port->oc_changed == 1 && port->flags & S3C_HCDFLG_USED) { dev_dbg(hcd->self.controller, "oc change on port %d\n", portno); if (orig < 1) orig = 1; buf[0] |= 1<<(portno+1); } } return orig; } /* s3c2410_usb_set_power * * configure the power on a port, by calling the platform device * routine registered with the platform device */ static void s3c2410_usb_set_power(struct s3c2410_hcd_info *info, int port, int to) { if (info == NULL) return; if (info->power_control != NULL) { info->port[port-1].power = to; (info->power_control)(port-1, to); } } /* ohci_s3c2410_hub_control * * look at control requests to the hub, and see if we need * to take any action or over-ride the results from the * request. */ static int ohci_s3c2410_hub_control ( struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { struct s3c2410_hcd_info *info = to_s3c2410_info(hcd); struct usb_hub_descriptor *desc; int ret = -EINVAL; u32 *data = (u32 *)buf; dev_dbg(hcd->self.controller, "s3c2410_hub_control(%p,0x%04x,0x%04x,0x%04x,%p,%04x)\n", hcd, typeReq, wValue, wIndex, buf, wLength); /* if we are only an humble host without any special capabilities * process the request straight away and exit */ if (info == NULL) { ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); goto out; } /* check the request to see if it needs handling */ switch (typeReq) { case SetPortFeature: if (wValue == USB_PORT_FEAT_POWER) { dev_dbg(hcd->self.controller, "SetPortFeat: POWER\n"); s3c2410_usb_set_power(info, wIndex, 1); goto out; } break; case ClearPortFeature: switch (wValue) { case USB_PORT_FEAT_C_OVER_CURRENT: dev_dbg(hcd->self.controller, "ClearPortFeature: C_OVER_CURRENT\n"); if (valid_port(wIndex)) { info->port[wIndex-1].oc_changed = 0; info->port[wIndex-1].oc_status = 0; } goto out; case USB_PORT_FEAT_OVER_CURRENT: dev_dbg(hcd->self.controller, "ClearPortFeature: OVER_CURRENT\n"); if (valid_port(wIndex)) { info->port[wIndex-1].oc_status = 0; } goto out; case USB_PORT_FEAT_POWER: dev_dbg(hcd->self.controller, "ClearPortFeature: POWER\n"); if (valid_port(wIndex)) { s3c2410_usb_set_power(info, wIndex, 0); return 0; } } break; } ret = ohci_hub_control(hcd, typeReq, wValue, wIndex, buf, wLength); if (ret) goto out; switch (typeReq) { case GetHubDescriptor: /* update the hub's descriptor */ desc = (struct usb_hub_descriptor *)buf; if (info->power_control == NULL) return ret; dev_dbg(hcd->self.controller, "wHubCharacteristics 0x%04x\n", desc->wHubCharacteristics); /* remove the old configurations for power-switching, and * over-current protection, and insert our new configuration */ desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_LPSM); desc->wHubCharacteristics |= cpu_to_le16(0x0001); if (info->enable_oc) { desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM); desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001); } dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n", desc->wHubCharacteristics); return ret; case GetPortStatus: /* check port status */ dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex); if (valid_port(wIndex)) { if (info->port[wIndex-1].oc_changed) { *data |= cpu_to_le32(RH_PS_OCIC); } if (info->port[wIndex-1].oc_status) { *data |= cpu_to_le32(RH_PS_POCI); } } } out: return ret; } /* s3c2410_hcd_oc * * handle an over-current report */ static void s3c2410_hcd_oc(struct s3c2410_hcd_info *info, int port_oc) { struct s3c2410_hcd_port *port; struct usb_hcd *hcd; unsigned long flags; int portno; if (info == NULL) return; port = &info->port[0]; hcd = info->hcd; local_irq_save(flags); for (portno = 0; portno < 2; port++, portno++) { if (port_oc & (1<flags & S3C_HCDFLG_USED) { port->oc_status = 1; port->oc_changed = 1; /* ok, once over-current is detected, the port needs to be powered down */ s3c2410_usb_set_power(info, portno+1, 0); } } local_irq_restore(flags); } /* may be called without controller electrically present */ /* may be called with controller, bus, and devices active */ /* * usb_hcd_s3c2410_remove - shutdown processing for HCD * @dev: USB Host Controller being removed * Context: !in_interrupt() * * Reverses the effect of usb_hcd_3c2410_probe(), first invoking * the HCD's stop() method. It is always called from a thread * context, normally "rmmod", "apmd", or something similar. * */ static void usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev) { usb_remove_hcd(hcd); s3c2410_stop_hc(dev); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); #ifdef CONFIG_QISDA_E600_EVT2 writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT); //#elif CONFIG_QISDA_AS090B00_EVT1 #else /*Qisda,Leo SJ Yang,2009/09/09{*/ /*Fix 3G Module can not work after running mass storage*/ #ifdef CONFIG_USB_GADGET if( g_EMUSBTestIsOK!=1) { writel((readl(S3C2410_GPHDAT)&~(1<<14)),S3C2410_GPHDAT); } #endif /*}Qisda,Leo SJ Yang,2009/09/09*/ /*Fix 3G Module can not work after running mass storage*/ writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT); #endif } //Qisda, Leo SJ Yang, 2009/08/31, for 3G power { #define S3C_3G_POWER_ON 1 #define S3C_3G_POWER_OFF 2 #define USB_3G_DEVICE_POWER_STATE 10 /*Qisda, 2009/10/9 Leo SJ Yang*/ /*fix the problem,the message "show can not enable port" is printed when there is no 3G module {*/ struct usb_hcd *g_phcd=NULL; struct platform_device *g_pdev=NULL; struct hc_driver *g_pdriver=NULL; /*}Qisda, 2009/10/9 Leo SJ Yang*/ /*fix the problem,the message "show can not enable port" is printed when there is no 3G module */ static int s3c_3G_open(struct inode *inode, struct file *file) { return 0; } static int s3c_3G_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { int retval; static char s3c_3Gpower_off = 1; static int USB_3G_POWER_SAVING = 0; switch(cmd){ case S3C_3G_POWER_ON: USB_3G_DEVICE_POWER_STATE_D0: if(USB_3G_POWER_SAVING == 1){ //printk("\n== D1 -> D0\n"); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<8), S3C2410_GPHDAT); USB_3G_POWER_SAVING = 0; return 0; } #ifdef CONFIG_QISDA_E600_EVT2 writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<14), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<8), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<23)) | 1<<22), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<11), S3C2410_GPHDAT); s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_OUTP); s3c2410_gpio_setpin(S3C2410_GPD14,1); /* usb power enbale */ #endif //CONFIG_QISDA_E600_EVT2 #ifdef CONFIG_QISDA_AS090B00_EVT1 /*Qisda,Leo.SJ.Yang,2009/09/21{*/ /*Avoid 3G module comsumes more current during turn on 3G power*/ /*set 3G_DIABLE pin as high after set 3G_DISABLE pin as low delay 3 second*/ writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<14), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) &~(1<<8), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<23)) | 1<<22), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<11), S3C2410_GPHDAT); mdelay(5000); writel(readl(S3C2410_GPHDAT)|(1<<8), S3C2410_GPHDAT); /*}Qisda,Leo.SJ.Yang,2009/09/21*/ /*Avoid 3G module comsumes more int retval;current during turn on 3G power*/ /*set 3G_DIABLE pin as high after set 3G_DISABLE pin as low delay 3 second*/ #endif //CONFIG_QISDA_AS090B00_EVT1 #if defined(CONFIG_QISDA_AS090B00_EVT1_1)||defined(CONFIG_QISDA_QD090B00_EVT1) writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<14), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) &~(1<<8), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<23)) | 1<<22), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) &~(1<<11), S3C2410_GPHDAT); writel(((readl(S3C2410_GPGCON) & ~(1<<7)) | 1<<6), S3C2410_GPGCON); writel(readl(S3C2410_GPGDAT) |(1<<3), S3C2410_GPGDAT); //s3c2410_gpio_pullup(S3C2410_GPG3, 2); /* usb power enbale */ //mdelay(100); /*2009/10/21 ,Qisda,Leo SJ Yang*/ /*3G will voltage over 3.6V if charging capcity for 100 msec*/ /*change the time of charging from 100 msec to 65 msec{*/ mdelay(65); /*}2009/10/21 ,Qisda,Leo SJ Yang*/ writel(readl(S3C2410_GPHDAT) |(1<<11), S3C2410_GPHDAT); s3c2410_gpio_pullup(S3C2410_GPH11, 2); /* usb power enbale */ mdelay(1); writel(readl(S3C2410_GPGDAT) &~(1<<3), S3C2410_GPGDAT); //s3c2410_gpio_pullup(S3C2410_GPG3, 1); /* usb power enbale */ mdelay(1); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<8), S3C2410_GPHDAT); s3c2410_gpio_pullup(S3C2410_GPH8, 2); /* usb power enbale */ #endif //CONFIG_QISDA_AS090B00_EVT1_1 s3c_3Gpower_off = 0; if(g_phcd==NULL) { s3c2410_usb_set_power(g_pdev->dev.platform_data, 1, 1); s3c2410_usb_set_power(g_pdev->dev.platform_data, 2, 1); g_phcd = usb_create_hcd(g_pdriver, &g_pdev->dev, "s3c24xx"); if (g_phcd == NULL) return -ENOMEM; g_phcd->rsrc_start = g_pdev->resource[0].start; g_phcd->rsrc_len = g_pdev->resource[0].end - g_pdev->resource[0].start + 1; if (!request_mem_region(g_phcd->rsrc_start,g_phcd->rsrc_len, hcd_name)) { dev_err(&g_pdev->dev, "request_mem_region failed"); retval = -EBUSY; goto err_put; } clk = clk_get(&g_pdev->dev, "usb-host"); if (IS_ERR(clk)) { dev_err(&g_pdev->dev, "cannot get usb-host clock\n"); retval = -ENOENT; goto err_mem; } #if !defined(CONFIG_CPU_S3C6400) && !defined(CONFIG_CPU_S3C6410) usb_clk = clk_get(&g_pdev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { dev_err(&g_pdev->dev, "cannot get usb-host clock\n"); retval = -ENOENT; goto err_clk; } #endif s3c2410_start_hc(g_pdev,g_phcd); g_phcd->regs = ioremap(g_phcd->rsrc_start,g_phcd->rsrc_len); if (!g_phcd->regs) { dev_err(&g_pdev->dev, "ioremap failed\n"); retval = -ENOMEM; goto err_ioremap; } ohci_hcd_init(hcd_to_ohci(g_phcd)); retval = usb_add_hcd(g_phcd, g_pdev->resource[1].start, IRQF_DISABLED); if (retval != 0) goto err_ioremap; return 0; err_ioremap: s3c2410_stop_hc(g_pdev); iounmap(g_phcd->regs); clk_put(usb_clk); #if !defined(CONFIG_CPU_S3C6400) && !defined(CONFIG_CPU_S3C6410) err_clk: clk_put(clk); #endif err_mem: release_mem_region(g_phcd->rsrc_start,g_phcd->rsrc_len); err_put: usb_put_hcd(g_phcd); } break; case S3C_3G_POWER_OFF: USB_3G_DEVICE_POWER_STATE_D3: //printk("S3C_WIFI_POWER_OFF"); if(!s3c_3Gpower_off){ #ifdef CONFIG_QISDA_E600_EVT1_1 writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT); #endif #ifdef CONFIG_QISDA_AS090B00_EVT1 /*Qisda,Leo SJ Yang,2009/09/09{*/ /*Fix 3G Module can not work after running mass storage*/ #ifdef CONFIG_USB_GADGET if( g_EMUSBTestIsOK!=1) { writel((readl(S3C2410_GPHDAT)&~(1<<14)),S3C2410_GPHDAT); } #endif /*}Qisda,Leo SJ Yang,2009/09/09*/ /*Fix 3G Module can not work after running mass storage*/ writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT); #endif #if defined(CONFIG_QISDA_AS090B00_EVT1_1)|| defined(CONFIG_QISDA_QD090B00_EVT1) writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT); writel((readl(S3C2410_GPGDAT)&~(1<<3)),S3C2410_GPGDAT); s3c2410_gpio_pullup(S3C2410_GPH11, 1); /* usb power enbale */ s3c2410_gpio_pullup(S3C2410_GPH8, 1); /* usb power enbale */ #endif s3c_3Gpower_off = 1; USB_3G_POWER_SAVING = 0; } break; case USB_3G_DEVICE_POWER_STATE: printk("\nUSB_3G_DEVICE_POWER_STATE: %d\n", arg); #if defined(CONFIG_QISDA_AS090B00_EVT1_1)|| defined(CONFIG_QISDA_QD090B00_EVT1) if(arg == 0){ goto USB_3G_DEVICE_POWER_STATE_D0; } else if(arg == 3){ goto USB_3G_DEVICE_POWER_STATE_D3; } else if((arg == 2) || (arg == 1)){ if(!s3c_3Gpower_off){ //printk("\nGPH8 low\n"); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) & ~(1<<8), S3C2410_GPHDAT); s3c2410_gpio_pullup(S3C2410_GPH8, 1); /* usb power enbale */ USB_3G_POWER_SAVING = 1; } } #endif break; default: printk("no this command\n"); break; } return 0; } /* File operations struct for character device */ static const struct file_operations s3c_3G_fops = { .owner = THIS_MODULE, .ioctl = s3c_3G_ioctl, .open = s3c_3G_open, .release = NULL }; //Qisda, Leo SJ Yang, 2009/08/31, for 3G power } /**/ /** * usb_hcd_s3c2410_probe - initialize S3C2410-based HCDs * Context: !in_interrupt() * * Allocates basic resources for this USB host controller, and * then invokes the start() methint retval;int retval;od for the HCD associated with it * through the hotplug entry's driver_data. * */ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, struct platform_device *dev) { // struct usb_hcd *hcd = NULL; // int retval; g_pdev=dev; g_pdriver=driver; /*Qisda,Leo SJ Yang,2009/09/10{*/ /*Mark the code that is not used */ #if 0 #if defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416) /* USB host Power enable */ s3c2410_gpio_cfgpin(S3C2410_GPB4, S3C2410_GPB4_OUTP); s3c2410_gpio_pullup(S3C2410_GPB4, 0); s3c2410_gpio_setpin(S3C2410_GPB4, 1); #endif #endif /*}Qisda,Leo SJ Yang,2009/09/10*/ /*Mark the code that is not used */ #if (USB_HOST_PORT2_EN == 1) && (CONFIG_PLAT_S3C64XX == 1) /* set USB_SIG_MASK */ __raw_writel( __raw_readl(S3C_OTHERS)|(1<<16), S3C_OTHERS); /* Initializes OTG PHY */ __raw_writel(0x0, S3C_USBOTG_PHYPWR); raw_writel(0x60, S3C_USBOTG_PHYCLK); __raw_writel(0x1, S3C_USBOTG_RSTCON); udelay(20); __raw_writel(0x0, S3C_USBOTG_RSTCON); udelay(20); #endif #ifdef CONFIG_QISDA_E600_EVT0 /*Qisda,2009/7/29,Leo SJ Yang{*/ /*HW EVT0,Config C_MODE,USB_SEL,USB20_EN for USB Host*/ //GPH14 writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<14), S3C2410_GPHDAT); //GPK6 writel(((readl(S3C2416_GPKCON) & ~(1<<13)) | 1<<12), S3C2416_GPKCON); writel(readl(S3C2416_GPKDAT)&~( 1<<6), S3C2416_GPKDAT); //GPK12 writel(((readl(S3C2416_GPKCON) & ~(1<<23)) | 1<<22), S3C2416_GPKCON); writel(readl(S3C2416_GPKDAT)|( 1<<11), S3C2416_GPKDAT); /*}Qisda,2009/7/29,Leo SJ Yang*/ /*HW EVT0,Config C_MODE,USB_SEL,USB20_EN for USB Host*/ #endif #ifdef CONFIG_QISDA_E600_EVT2 writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<14), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<8), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<23)) | 1<<22), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<11), S3C410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<19)) | 1<<18), S3C2410_GPHCON); s3c2410_gpio_cfgpin(S3C2410_GPD14, S3C2410_GPD14_OUTP); s3c2410_gpio_setpin(S3C2410_GPD14,1); /* usb power enbale */ /*}Qisda,Leo SJ Yang,2009/08/31,add file operation for enable and disable 3G Module*/ #endif #ifdef CONFIG_QISDA_AS090B00_EVT1 /*Qisda,Leo SJ Yang,2009/09/09{*/ /*Fix 3G Module can not work after running mass storage*/ writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); if( g_EMUSBTestIsOK!=1) writel(readl(S3C2410_GPHDAT)&~(1<<14), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(((readl(S3C2410_GPHCON) & ~(1<<23)) | 1<<22), S3C2410_GPHCON); writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT); /*}Qisda,Leo SJ Yang,2009/09/09*/ /*Fix 3G Module can not work after running mass storage*/ #endif #if defined(CONFIG_QISDA_AS090B00_EVT1_1)||defined(CONFIG_QISDA_QD090B00_EVT1) writel(((readl(S3C2410_GPHCON) & ~(1<<29)) | 1<<28), S3C2410_GPHCON); writel(readl(S3C2410_GPHDAT) |(1<<14), S3C2410_GPHDAT); writel(((readl(S3C2410_GPHCON) & ~(1<<17)) | 1<<16), S3C2410_GPHCON); writel(((readl(S3C2410_GPHCON) & ~(1<<23)) | 1<<22), S3C2410_GPHCON); writel(((readl(S3C2410_GPGCON) & ~(1<<7)) | 1<<6), S3C2410_GPGCON); writel((readl(S3C2410_GPHDAT)&~(1<<11)),S3C2410_GPHDAT); //on/off writel(readl(S3C2410_GPHDAT)&~(1<<8), S3C2410_GPHDAT);//disable writel(readl(S3C2410_GPGDAT)&~(1<<3), S3C2410_GPGDAT);//audio reset #endif if (register_chrdev (S3C_3G_MAJOR, "s3c_3G_cmd", &s3c_3G_fops)) { printk("unable to get major S3C_3G_MAJOR\n"); } #if 0 s3c2410_usb_set_power(dev->dev.platform_data, 1, 1); s3c2410_usb_set_power(dev->dev.platform_data, 2, 1); hcd = usb_create_hcd(driver, &dev->dev, "s3c24xx"); if (hcd == NULL) return -ENOMEM; hcd->rsrc_start = dev->resource[0].start; hcd->rsrc_len = dev->resource[0].end - dev->resource[0].start + 1; if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { dev_err(&dev->dev, "request_mem_region failed"); retval = -EBUSY; goto err_put; } clk = clk_get(&dev->dev, "usb-host"); if (IS_ERR(clk)) { dev_err(&dev->dev, "cannot get usb-host clock\n"); retval = -ENOENT; goto err_mem; } #if (USB_HOST_PORT2_EN == 1) && (CONFIG_PLAT_S3C64XX == 1) otg_clk = clk_get(&dev->dev, "otg"); if (IS_ERR(clk)) { dev_err(&dev->dev, "cannot get otg clock\n"); retval = -ENOENT; goto err_mem; } #endif #if !defined(CONFIG_CPU_S3C6400) && !defined(CONFIG_CPU_S3C6410) usb_clk = clk_get(&dev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { dev_err(&dev->dev, "cannot get usb-host clock\n"); retval = -ENOENT; goto err_clk; } #endif s3c2410_start_hc(dev, hcd); hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&dev->dev, "ioremap failed\n"); retval = -ENOMEM; goto err_ioremap; } ohci_hcd_init(hcd_to_ohci(hcd)); retval = usb_add_hcd(hcd, dev->resource[1].start, IRQF_DISABLED); if (retval != 0) goto err_ioremap; return 0; err_ioremap: s3c2410_stop_hc(dev); iounmap(hcd->regs); clk_put(usb_clk); #if !defined(CONFIG_CPU_S3C6400) && !defined(CONFIG_CPU_S3C6410) err_clk: clk_put(clk); #endif err_mem: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put: usb_put_hcd(hcd); return retval; #endif return 0; } /*-------------------------------------------------------------------------*/ static int ohci_s3c2410_start (struct usb_hcd *hcd) { struct ohci_hcd *ohci = hcd_to_ohci (hcd); int ret; if ((ret = ohci_init(ohci)) < 0) return ret; if ((ret = ohci_run (ohci)) < 0) { err ("can't start %s", hcd->self.bus_name); ohci_stop (hcd); return ret; } return 0; } static const struct hc_driver ohci_s3c2410_hc_driver = { .description = hcd_name, .product_desc = "S3C24XX OHCI", .hcd_priv_size = sizeof(struct ohci_hcd), /* * generic hardware linkage */ .irq = ohci_irq, .flags = HCD_USB11 | HCD_MEMORY, /* * basic lifecycle operations */ .start = ohci_s3c2410_start, .stop = ohci_stop, .shutdown = ohci_shutdown, /* * managing i/o requests and associated device resources */ .urb_enqueue = ohci_urb_enqueue, .urb_dequeue = ohci_urb_dequeue, .endpoint_disable = ohci_endpoint_disable, /* * scheduling support */ .get_frame_number = ohci_get_frame, /* * root hub support */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, #endif .start_port_reset = ohci_start_port_reset, }; /* device driver */ static int ohci_hcd_s3c2410_drv_probe(struct platform_device *pdev) { return usb_hcd_s3c2410_probe(&ohci_s3c2410_hc_driver, pdev); } static int ohci_hcd_s3c2410_drv_remove(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_hcd_s3c2410_remove(hcd, pdev); return 0; } static int ohci_hcd_s3c2410_drv_shutdown(struct platform_device *pdev) { return 0; } static struct platform_driver ohci_hcd_s3c2410_driver = { .probe = ohci_hcd_s3c2410_drv_probe, .remove = ohci_hcd_s3c2410_drv_remove, //.shutdown = usb_hcd_platform_shutdown, /*2009/10/21 Qisda Leo SJ Yang*/ /*system crash after executing reboot{*/ .shutdown =ohci_hcd_s3c2410_drv_shutdown, /*}2009/10/21 Qisda Leo SJ Yang*/ /*system crash after executing reboot*/ /*.suspend = ohci_hcd_s3c2410_drv_suspend, */ /*.resume = ohci_hcd_s3c2410_drv_resume, */ .driver = { .owner = THIS_MODULE, .name = "s3c2410-ohci", }, };