/* * linux/arch/arm/mach-mmp/devices.c * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include #include #include #include #include #include "irqs.h" #include "devices.h" #include "cputype.h" #include "regs-usb.h" int __init pxa_register_device(struct pxa_device_desc *desc, void *data, size_t size) { struct platform_device *pdev; struct resource res[2 + MAX_RESOURCE_DMA]; int i, ret = 0, nres = 0; pdev = platform_device_alloc(desc->drv_name, desc->id); if (pdev == NULL) return -ENOMEM; pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); memset(res, 0, sizeof(res)); if (desc->start != -1ul && desc->size > 0) { res[nres].start = desc->start; res[nres].end = desc->start + desc->size - 1; res[nres].flags = IORESOURCE_MEM; nres++; } if (desc->irq != NO_IRQ) { res[nres].start = desc->irq; res[nres].end = desc->irq; res[nres].flags = IORESOURCE_IRQ; nres++; } for (i = 0; i < MAX_RESOURCE_DMA; i++, nres++) { if (desc->dma[i] == 0) break; res[nres].start = desc->dma[i]; res[nres].end = desc->dma[i]; res[nres].flags = IORESOURCE_DMA; } ret = platform_device_add_resources(pdev, res, nres); if (ret) { platform_device_put(pdev); return ret; } if (data && size) { ret = platform_device_add_data(pdev, data, size); if (ret) { platform_device_put(pdev); return ret; } } return platform_device_add(pdev); } #if IS_ENABLED(CONFIG_USB) || IS_ENABLED(CONFIG_USB_GADGET) #if IS_ENABLED(CONFIG_USB_MV_UDC) || IS_ENABLED(CONFIG_USB_EHCI_MV) #if IS_ENABLED(CONFIG_CPU_PXA910) || IS_ENABLED(CONFIG_CPU_PXA168) /***************************************************************************** * The registers read/write routines *****************************************************************************/ static unsigned int u2o_get(void __iomem *base, unsigned int offset) { return readl_relaxed(base + offset); } static void u2o_set(void __iomem *base, unsigned int offset, unsigned int value) { u32 reg; reg = readl_relaxed(base + offset); reg |= value; writel_relaxed(reg, base + offset); readl_relaxed(base + offset); } static void u2o_clear(void __iomem *base, unsigned int offset, unsigned int value) { u32 reg; reg = readl_relaxed(base + offset); reg &= ~value; writel_relaxed(reg, base + offset); readl_relaxed(base + offset); } static void u2o_write(void __iomem *base, unsigned int offset, unsigned int value) { writel_relaxed(value, base + offset); readl_relaxed(base + offset); } static DEFINE_MUTEX(phy_lock); static int phy_init_cnt; static int usb_phy_init_internal(void __iomem *base) { int loops; pr_info("Init usb phy!!!\n"); /* Initialize the USB PHY power */ if (cpu_is_pxa910()) { u2o_set(base, UTMI_CTRL, (1< 100) { printk(KERN_WARNING "calibrate timeout, UTMI_PLL %x\n", u2o_get(base, UTMI_PLL)); break; } } if (cpu_is_pxa168()) { u2o_set(base, UTMI_RESERVE, 1 << 5); /* Turn on UTMI PHY OTG extension */ u2o_write(base, UTMI_OTG_ADDON, 1); } return 0; } static int usb_phy_deinit_internal(void __iomem *base) { pr_info("Deinit usb phy!!!\n"); if (cpu_is_pxa168()) u2o_clear(base, UTMI_OTG_ADDON, UTMI_OTG_ADDON_OTG_ON); u2o_clear(base, UTMI_CTRL, UTMI_CTRL_RXBUF_PDWN); u2o_clear(base, UTMI_CTRL, UTMI_CTRL_TXBUF_PDWN); u2o_clear(base, UTMI_CTRL, UTMI_CTRL_USB_CLK_EN); u2o_clear(base, UTMI_CTRL, 1<