📄 dwc_otg_driver.c
字号:
* Remove the device attributes * by scsuh */// dwc_otg_attr_remove(dev); /* * Return the memory. */ if (otg_dev->base != NULL) { iounmap(otg_dev->base); } kfree(otg_dev); /* * Clear the drvdata pointer. */ platform_set_drvdata(dev, 0); return 0;}static struct clk *otg_clock = NULL;static dwc_otg_core_if_t *core_if_global;/** * 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[in] _lmdev lm_device definition */static int dwc_otg_driver_probe (struct platform_device *pdev){ int retval = 0; dwc_otg_device_t *dwc_otg_device; uint reg; dbg_otg("%s\n", __FUNCTION__); dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL); if (dwc_otg_device == 0) { dev_err(&pdev->dev, "kmalloc of dwc_otg_device failed\n"); retval = -ENOMEM; goto fail; } memset(dwc_otg_device, 0, sizeof(*dwc_otg_device)); dwc_otg_device->reg_offset = 0xFFFFFFFF; /* * enable hclk using clk_enable() * by scsuh. * special modification for S3C64xx */ otg_clock = clk_get(&pdev->dev, "otg"); if (otg_clock == NULL) { printk(KERN_INFO "failed to find otg clock source\n"); return -ENOENT; } clk_enable(otg_clock); /* * very important init code for S3C64xx * by scsuh. * special modification for S3C64xx */ { uint temp; temp = __raw_readl(S3C_OTHERS); temp |= (1<<16); // USB_SIG_MASK __raw_writel(temp, S3C_OTHERS); /* 1. Initializes OTG Phy. */ __raw_writel(0x0, S3C_USBOTG_PHYPWR); __raw_writel(0x20, S3C_USBOTG_PHYCLK); __raw_writel(0x1, S3C_USBOTG_RSTCON); udelay(50); __raw_writel(0x0, S3C_USBOTG_RSTCON); udelay(50); } /* * Map the DWC_otg Core memory into virtual address space. * in S3C64xx we already have virtual address for OTG. * modified by scsuh. */#if 0 dwc_otg_device->base = ioremap(XXXX, SZ_256K); if (dwc_otg_device->base == NULL) { dev_err(&pdev->dev, "ioremap() failed\n"); retval = -ENOMEM; goto fail; }#else dwc_otg_device->base = S3C24XX_VA_OTG;#endif dbg_otg("base=0x%08x\n", (unsigned) dwc_otg_device->base); /* * Attempt to ensure this device is really a DWC_otg Controller. * Read and verify the SNPSID register contents. The value should be * 0x45F42XXX, which corresponds to "OT2", as in "OTG version 2.XX". */ reg = dwc_read_reg32((uint32_t *) ((uint8_t *) dwc_otg_device->base + 0x40)); if ((reg & 0xFFFFF000) != 0x4F542000) { printk("Bad value for SNPSID: 0x%08x\n", reg); retval = -EINVAL; goto fail; } /* * Initialize driver data to point to the global DWC_otg * Device structure. */ platform_set_drvdata(pdev, dwc_otg_device); printk("dwc_otg_device=0x%p\n", dwc_otg_device); dwc_otg_device->core_if = dwc_otg_cil_init(dwc_otg_device->base, &dwc_otg_module_params); if (dwc_otg_device->core_if == 0) { printk("CIL initialization failed!\n"); retval = -ENOMEM; goto fail; } core_if_global = dwc_otg_device->core_if; /* * Validate parameter values. */ if (check_parameters(dwc_otg_device->core_if) != 0) { retval = -EINVAL; goto fail; } /* * Create Device Attributes in sysfs * rem by scsuh. */// dwc_otg_attr_create(pdev); /* * Disable the global interrupt until all the interrupt * handlers are installed. */ dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); /* * Install the interrupt handler for the common interrupts before * enabling common interrupts in core_init below. */ dbg_otg("registering (common) handler for irq%d\n", IRQ_OTG); retval = request_irq(IRQ_OTG, dwc_otg_common_irq, SA_SHIRQ, "dwc_otg", dwc_otg_device); if (retval != 0) { printk("request of irq%d failed\n", IRQ_OTG); retval = -EBUSY; goto fail; } else { dwc_otg_device->common_irq_installed = 1; } /* * Initialize the DWC_otg core. */ dwc_otg_core_init(dwc_otg_device->core_if);#ifndef DWC_HOST_ONLY /* * Initialize the PCD */ retval = dwc_otg_pcd_init(pdev); if (retval != 0) { printk("dwc_otg_pcd_init failed\n"); dwc_otg_device->pcd = NULL; goto fail; }#endif#ifndef DWC_DEVICE_ONLY /* * Initialize the HCD */ retval = dwc_otg_hcd_init(pdev); if (retval != 0) { printk("dwc_otg_hcd_init failed\n"); dwc_otg_device->hcd = NULL; goto fail; }#endif /* * Enable the global interrupt after all the interrupt * handlers are installed. */#if 0 dwc_otg_enable_global_interrupts(dwc_otg_device->core_if);#else reg = readl(S3C_UDC_OTG_GAHBCFG); writel(reg | 1, S3C_UDC_OTG_GAHBCFG);#endif return 0;fail: dwc_otg_driver_remove(pdev); return retval;}/** * This structure defines the methods to be called by a bus driver * during the lifecycle of a device on that bus. Both drivers and * devices are registered with a bus driver. The bus driver matches * devices to drivers based on information in the device and driver * structures. * * The probe function is called when the bus driver matches a device * to this driver. The remove function is called when a device is * unregistered with the bus driver. */static struct platform_driver dwc_otg_driver = { .probe = dwc_otg_driver_probe, .remove = dwc_otg_driver_remove, .driver = { .name = "s3c2410-usbgadget", .owner = THIS_MODULE, },};/** * This function is called when the dwc_otg_driver is installed with the * insmod command. It registers the dwc_otg_driver structure with the * appropriate bus driver. This will cause the dwc_otg_driver_probe function * to be called. In addition, the bus driver will automatically expose * attributes defined for the device and driver in the special sysfs file * system. * * @return */static int __init dwc_otg_driver_init(void){ int retval = 0; printk(KERN_INFO "%s: version %s\n", dwc_driver_name, DWC_DRIVER_VERSION); printk(KERN_INFO "Working version %s\n", "No 007 - 10/24/2007"); retval = platform_driver_register(&dwc_otg_driver); if (retval < 0) { printk(KERN_ERR "%s retval=%d\n", __func__, retval); }// driver_create_file(&dwc_otg_driver.drv, &driver_attr_version);// driver_create_file(&dwc_otg_driver.drv, &driver_attr_debuglevel); return retval;}module_init(dwc_otg_driver_init);/** * This function is called when the driver is removed from the kernel * with the rmmod command. The driver unregisters itself with its bus * driver. * */static void __exit dwc_otg_driver_cleanup(void){ printk(KERN_DEBUG "dwc_otg_driver_cleanup()\n");// driver_remove_file(&dwc_otg_driver.drv, &driver_attr_debuglevel);// driver_remove_file(&dwc_otg_driver.drv, &driver_attr_version); platform_driver_unregister(&dwc_otg_driver); printk(KERN_INFO "%s module removed\n", dwc_driver_name);}module_exit(dwc_otg_driver_cleanup);MODULE_DESCRIPTION(DWC_DRIVER_DESC);MODULE_AUTHOR("Synopsys Inc.");MODULE_LICENSE("GPL");module_param_named(otg_cap, dwc_otg_module_params.otg_cap, int, 0444);MODULE_PARM_DESC(otg_cap, "OTG Capabilities 0=HNP&SRP 1=SRP Only 2=None");module_param_named(opt, dwc_otg_module_params.opt, int, 0444);MODULE_PARM_DESC(opt, "OPT Mode");module_param_named(dma_enable, dwc_otg_module_params.dma_enable, int, 0444);MODULE_PARM_DESC(dma_enable, "DMA Mode 0=Slave 1=DMA enabled");module_param_named(dma_desc_enable, dwc_otg_module_params.dma_desc_enable, int, 0444);MODULE_PARM_DESC(dma_desc_enable, "DMA Desc Mode 0=Address DMA 1=DMA Descriptor enabled");module_param_named(dma_burst_size, dwc_otg_module_params.dma_burst_size, int, 0444);MODULE_PARM_DESC(dma_burst_size, "DMA Burst Size 1, 4, 8, 16, 32, 64, 128, 256");module_param_named(speed, dwc_otg_module_params.speed, int, 0444);MODULE_PARM_DESC(speed, "Speed 0=High Speed 1=Full Speed");module_param_named(host_support_fs_ls_low_power, dwc_otg_module_params.host_support_fs_ls_low_power, int, 0444);MODULE_PARM_DESC(host_support_fs_ls_low_power, "Support Low Power w/FS or LS 0=Support 1=Don't Support");module_param_named(host_ls_low_power_phy_clk, dwc_otg_module_params.host_ls_low_power_phy_clk, int, 0444);MODULE_PARM_DESC(host_ls_low_power_phy_clk, "Low Speed Low Power Clock 0=48Mhz 1=6Mhz");module_param_named(enable_dynamic_fifo, dwc_otg_module_params.enable_dynamic_fifo, int, 0444);MODULE_PARM_DESC(enable_dynamic_fifo, "0=cC Setting 1=Allow Dynamic Sizing");module_param_named(data_fifo_size, dwc_otg_module_params.data_fifo_size, int, 0444);MODULE_PARM_DESC(data_fifo_size, "Total number of words in the data FIFO memory 32-32768");module_param_named(dev_rx_fifo_size, dwc_otg_module_params.dev_rx_fifo_size, int, 0444);MODULE_PARM_DESC(dev_rx_fifo_size, "Number of words in the Rx FIFO 16-32768");module_param_named(dev_nperio_tx_fifo_size, dwc_otg_module_params.dev_nperio_tx_fifo_size, int, 0444);MODULE_PARM_DESC(dev_nperio_tx_fifo_size, "Number of words in the non-periodic Tx FIFO 16-32768");module_param_named(dev_perio_tx_fifo_size_1, dwc_otg_module_params.dev_perio_tx_fifo_size[0], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_1, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_2, dwc_otg_module_params.dev_perio_tx_fifo_size[1], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_2, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_3, dwc_otg_module_params.dev_perio_tx_fifo_size[2], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_3, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_4, dwc_otg_module_params.dev_perio_tx_fifo_size[3], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_4, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_5, dwc_otg_module_params.dev_perio_tx_fifo_size[4], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_5, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_6, dwc_otg_module_params.dev_perio_tx_fifo_size[5], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_6, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_7, dwc_otg_module_params.dev_perio_tx_fifo_size[6], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_7, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_8, dwc_otg_module_params.dev_perio_tx_fifo_size[7], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_8, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_9, dwc_otg_module_params.dev_perio_tx_fifo_size[8], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_9, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_10, dwc_otg_module_params.dev_perio_tx_fifo_size[9], int, 0444);MODULE_PARM_DESC(dev_perio_tx_fifo_size_10, "Number of words in the periodic Tx FIFO 4-768");module_param_named(dev_perio_tx_fifo_size_11, dwc_otg_module_params.dev_perio_tx_fifo_size[10], int, 0444);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -