/* * U-Boot USB interface */ int usb_lowlevel_init(int index, void **controller) { /* * We need doubleword-aligned buffers for DMA transfers */ allocated_buffer = (uint8_t *)malloc(DWC_OTG_HCD_STATUS_BUF_SIZE + DWC_OTG_HCD_DATA_BUF_SIZE + 8); uint32_t addr = (uint32_t)allocated_buffer; aligned_buffer = (uint8_t *) ((addr + 7) & ~7); status_buffer = (uint8_t *)((uint32_t)aligned_buffer + DWC_OTG_HCD_DATA_BUF_SIZE); int i, j; hprt0_data_t hprt0 = {.d32 = 0 }; root_hub_devnum = 0; memset(&g_core_if, 0, sizeof(g_core_if)); dwc_otg_cil_init(&g_core_if, (uint32_t *)CONFIG_SYS_USB_ADDRESS); if ((g_core_if.snpsid & 0xFFFFF000) != 0x4F542000) { printf("SNPSID is invalid (not DWC OTG device): %08x\n", g_core_if.snpsid); return -1; } dwc_otg_core_init(&g_core_if); dwc_otg_core_host_init(&g_core_if); hprt0.d32 = dwc_otg_read_hprt0(&g_core_if); hprt0.b.prtrst = 1; dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32); mdelay(50); hprt0.b.prtrst = 0; dwc_write_reg32(g_core_if.host_if->hprt0, hprt0.d32); for (i = 0; i < MAX_DEVICE; i++) { for (j = 0; j < MAX_ENDPOINT; j++) { control_data_toggle[i][j] = DWC_OTG_HC_PID_DATA1; bulk_data_toggle[i][j] = DWC_OTG_HC_PID_DATA0; } } return 0; } int usb_lowlevel_stop(int index) { free(allocated_buffer); return 0; }
/* * 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. * */ int usb_driver_init(uint32_t base_addr) { int retval = 0; __DWC_WARN("dwc_otg_driver_init\n"); dwc_otg_device = &static_data->dwc_otg_device_inst; DWC_MEMSET(dwc_otg_device, 0, sizeof(*dwc_otg_device)); /* * Initialize driver data to point to the global DWC_otg * Device structure. */ __DWC_ERROR("dwc_otg_device addr = 0x%p\n", dwc_otg_device); dwc_otg_device->core_if = dwc_otg_cil_init(base_addr); if (!dwc_otg_device->core_if) { __DWC_ERROR("CIL initialization failed!\n"); retval = -DWC_E_NO_MEMORY; goto fail; } #ifdef USB_DEBUG /* * Attempt to ensure this device is really a DWC_otg Controller. * Read and verify the SNPSID register contents. The value should be * 0x45F42XXX or 0x45F42XXX, which corresponds to either "OT2" or "OTG3", * as in "OTG version 2.XX" or "OTG version 3.XX". */ if (((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F542000) && ((dwc_otg_get_gsnpsid(dwc_otg_device->core_if) & 0xFFFFF000) != 0x4F543000)) { __DWC_WARN("Bad value for SNPSID: 0x%x\n", dwc_otg_get_gsnpsid(dwc_otg_device->core_if)); retval = -DWC_E_INVALID; goto fail; } #endif /* USB_DEBUG */ /* * Disable the global interrupt until all the interrupt * handlers are installed. */ __DWC_WARN("USB INIT: Disabling global IRQ\n"); dwc_otg_disable_global_interrupts(dwc_otg_device->core_if); /* * Initialize the DWC_otg core. */ __DWC_WARN("USB INIT: Initializing OTG core\n"); dwc_otg_core_init(dwc_otg_device->core_if); /* * Initialize the PCD */ __DWC_WARN("USB INIT: Initializing PCD\n"); retval = pcd_init(dwc_otg_device); if (retval != 0) { __DWC_ERROR("pcd_init failed\n"); dwc_otg_device->pcd = NULL; goto fail; } __DWC_WARN("USB INIT: Enabling global IRQ\n"); dwc_otg_enable_global_interrupts(dwc_otg_device->core_if); __DWC_WARN("DWC core initialized! \n"); return 0; fail: __DWC_ERROR("ERROR! unable to init USB driver\n"); return retval; }
static int __devinit dwc_otg_driver_probe(struct platform_device *ofdev) { int retval; struct dwc_otg_device *dwc_dev; struct device *dev = &ofdev->dev; struct resource res; ulong gusbcfg_addr; u32 usbcfg = 0; struct resource *nres = 0; #ifdef CONFIG_OF u32 prop; u32 prop_array[15]; #endif dwc_dev = kzalloc(sizeof(*dwc_dev), GFP_KERNEL); if (!dwc_dev) { dev_err(dev, "kmalloc of dwc_otg_device failed\n"); retval = -ENOMEM; goto fail_dwc_dev; } /* Retrieve the memory and IRQ resources. */ dwc_dev->irq = platform_get_irq(ofdev, 0); if (dwc_dev->irq == NO_IRQ) { dev_err(dev, "no device irq\n"); retval = -ENODEV; goto fail_of_irq; } nres = platform_get_resource(ofdev, IORESOURCE_MEM, 0); res = *nres; if(nres == 0) { dev_err(dev, "%s: Can't get USB-OTG register address\n", __func__); retval = -ENOMEM; goto fail_of_irq; } dwc_dev->phys_addr = res.start; dwc_dev->base_len = res.end - res.start + 1; if (!request_mem_region(dwc_dev->phys_addr, dwc_dev->base_len, dwc_driver_name)) { dev_err(dev, "request_mem_region failed\n"); retval = -EBUSY; goto fail_of_irq; } /* Map the DWC_otg Core memory into virtual address space. */ dwc_dev->base = ioremap(platform_get_resource(ofdev, IORESOURCE_MEM, 0)->start, SZ_256K); if (!dwc_dev->base) { dev_err(dev, "ioremap() failed\n"); retval = -ENOMEM; goto fail_ioremap; } dev_dbg(dev, "mapped base=0x%08x\n", (__force u32)dwc_dev->base); /* * Initialize driver data to point to the global DWC_otg * Device structure. */ dev_set_drvdata(dev, dwc_dev);//driver dwc_dev->core_if = dwc_otg_cil_init(dwc_dev->base, &dwc_otg_module_params); if (!dwc_dev->core_if) { dev_err(dev, "CIL initialization failed!\n"); retval = -ENOMEM; goto fail_cil_init; } /* * Set the wqfunc of this core_if as "not set" */ dwc_dev->core_if->wqfunc_setup_done = 0; /* * Validate parameter values after dwc_otg_cil_init. */ if (check_parameters(dwc_dev->core_if)) { retval = -EINVAL; goto fail_check_param; } #ifdef CONFIG_OF if(!of_property_read_u32(ofdev->dev.of_node, "dma-mask", (u32*)&dwc_otg_dma_mask)) { dev->dma_mask = &dwc_otg_dma_mask; } else { dev->dma_mask = NULL; } if(!of_property_read_u32(ofdev->dev.of_node, "ulpi-ddr", &prop)) { dwc_otg_module_params.phy_ulpi_ddr = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "host-rx-fifo-size", &prop)) { dwc_otg_module_params.host_rx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "dev-rx-fifo-size", &prop)) { dwc_otg_module_params.dev_rx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "host-nperio-tx-fifo-size", &prop)) { dwc_otg_module_params.host_nperio_tx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "dev-nperio-tx-fifo-size", &prop)) { dwc_otg_module_params.dev_nperio_tx_fifo_size = prop; } if(!of_property_read_u32(ofdev->dev.of_node, "host-perio-tx-fifo-size", &prop)) { dwc_otg_module_params.host_perio_tx_fifo_size = prop; } if(!of_property_read_u32_array(ofdev->dev.of_node, "dev-perio-tx-fifo-size", prop_array, MAX_PERIO_FIFOS)) { int i; for(i=0; i<MAX_PERIO_FIFOS; i++) dwc_otg_module_params.dev_tx_fifo_size[i] = prop_array[i]; } if(!of_property_read_u32_array(ofdev->dev.of_node, "dev-tx-fifo-size", prop_array, MAX_TX_FIFOS)) { int i; for(i=0; i<MAX_TX_FIFOS; i++) dwc_otg_module_params.dev_perio_tx_fifo_size[i] = prop_array[i]; } #endif usb_nop_xceiv_register(); dwc_dev->core_if->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (!dwc_dev->core_if->xceiv) { retval = -ENODEV; goto fail_xceiv; } dwc_set_feature(dwc_dev->core_if); /* Initialize the DWC_otg core. */ dwc_otg_core_init(dwc_dev->core_if); /* * Disable the global interrupt until all the interrupt * handlers are installed. */ spin_lock(&dwc_dev->lock); dwc_otg_disable_global_interrupts(dwc_dev->core_if); spin_unlock(&dwc_dev->lock); /* * Install the interrupt handler for the common interrupts before * enabling common interrupts in core_init below. */ retval = request_irq(dwc_dev->irq, dwc_otg_common_irq, IRQF_SHARED, "dwc_otg", dwc_dev); if (retval) { dev_err(dev, "request of irq%d failed retval: %d\n", dwc_dev->irq, retval); retval = -EBUSY; goto fail_req_irq; } else { dwc_dev->common_irq_installed = 1; } if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) { //if (dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) { /* Initialize the PCD */ retval = dwc_otg_pcd_init(dev); if (retval) { dev_err(dev, "dwc_otg_pcd_init failed\n"); dwc_dev->pcd = NULL; goto fail_req_irq; } } gusbcfg_addr = (ulong) (dwc_dev->core_if->core_global_regs) + DWC_GUSBCFG; if (!dwc_has_feature(dwc_dev->core_if, DWC_DEVICE_ONLY)) { //if (dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) { /* Initialize the HCD and force_host_mode */ usbcfg = dwc_reg_read(gusbcfg_addr, 0); usbcfg |= DWC_USBCFG_FRC_HST_MODE; dwc_reg_write(gusbcfg_addr, 0, usbcfg); retval = dwc_otg_hcd_init(dev, dwc_dev); if (retval) { dev_err(dev, "dwc_otg_hcd_init failed\n"); dwc_dev->hcd = NULL; goto fail_hcd; } /* configure chargepump interrupt */ dwc_dev->hcd->cp_irq = platform_get_irq_byname(ofdev, "chargepumpirq"); if(dwc_dev->hcd->cp_irq != -ENXIO) { retval = request_irq(dwc_dev->hcd->cp_irq, dwc_otg_externalchgpump_irq, IRQF_SHARED, "dwc_otg_ext_chg_pump", dwc_dev); if (retval) { dev_err(dev, "request of irq failed retval: %d\n", retval); retval = -EBUSY; goto fail_hcd; } else { dev_dbg(dev, "%s: ExtChgPump Detection " "IRQ registered\n", dwc_driver_name); } } } /* * Enable the global interrupt after all the interrupt * handlers are installed. */ dwc_otg_enable_global_interrupts(dwc_dev->core_if); #if 0 usbcfg = dwc_reg_read(gusbcfg_addr, 0); usbcfg &= ~DWC_USBCFG_FRC_HST_MODE; dwc_reg_write(gusbcfg_addr, 0, usbcfg); #endif return 0; fail_hcd: free_irq(dwc_dev->irq, dwc_dev); if (!dwc_has_feature(dwc_dev->core_if, DWC_HOST_ONLY)) { if (dwc_dev->pcd) dwc_otg_pcd_remove(dev); } fail_req_irq: usb_put_phy(dwc_dev->core_if->xceiv); fail_xceiv: usb_nop_xceiv_unregister(); fail_check_param: dwc_otg_cil_remove(dwc_dev->core_if); fail_cil_init: dev_set_drvdata(dev, NULL); iounmap(dwc_dev->base); fail_ioremap: release_mem_region(dwc_dev->phys_addr, dwc_dev->base_len); fail_of_irq: kfree(dwc_dev); fail_dwc_dev: return retval; }