Exemplo n.º 1
0
/*
 * 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;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
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;
}