_core_if->core_global_regs;
dwc_otg_dev_if_t *dev_if = _core_if->dev_if;
volatile dcfg_data_t dcfg = {.d32 = 0};
- volatile dctl_data_t dctl = {.d32 = 0};
- volatile grstctl_t grstctl = {.d32 = 0};
- volatile depctl_data_t depctl = {.d32 = 0};
- volatile daint_data_t daintmsk = {.d32 = 0};
- volatile gahbcfg_data_t gahbcfg = {.d32 = 0};
+ volatile dctl_data_t dctl = {.d32 = 0};
+ volatile grstctl_t grstctl = {.d32 = 0};
+ volatile depctl_data_t depctl = {.d32 = 0};
+ volatile daint_data_t daintmsk = {.d32 = 0};
+ volatile gahbcfg_data_t gahbcfg = {.d32 = 0};
volatile dthrctl_data_t dthrctl;
dwc_otg_core_reset(_core_if);
/* Restart the Phy Clock */
dwc_write_reg32(_core_if->pcgcctl, 0);
/* soft disconnect */
- dctl.d32 = dwc_read_reg32( &_core_if->dev_if->dev_global_regs->dctl );
- dctl.b.sftdiscon = 1;
- dwc_write_reg32( &_core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
+ dctl.d32 = dwc_read_reg32( &_core_if->dev_if->dev_global_regs->dctl );
+ dctl.b.sftdiscon = 1;
+ dwc_write_reg32( &_core_if->dev_if->dev_global_regs->dctl, dctl.d32 );
#ifdef CONFIG_ARCH_RK29
/* Configure data FIFO sizes, RK29 otg has 0x3c0 dwords total */
- dwc_write_reg32( &global_regs->grxfsiz, 0x00000210 );
- dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100210 ); //ep0 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000220 ); //ep1 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00100320 ); //ep3 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x00800330 ); //ep5 tx fifo
+ dwc_write_reg32( &global_regs->grxfsiz, 0x00000210 );
+ dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100210 ); //ep0 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000220 ); //ep1 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00100320 ); //ep3 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x00800330 ); //ep5 tx fifo
#else
#if !(defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188) || \
- defined(CONFIG_ARCH_RK2928)|| defined(CONFIG_ARCH_RK3026) )
- DWC_ERROR("Warning!!! Please Check USB Controller FIFO Configuration\n");
+ defined(CONFIG_ARCH_RK2928)|| defined(CONFIG_ARCH_RK3026) ||\
+ defined(CONFIG_ARCH_ROCKCHIP))
+ DWC_ERROR("Warning!!! Please Check USB Controller FIFO Configuration\n");
#endif
/* Configure data FIFO sizes, RK30 otg has 0x3cc dwords total */
- dwc_write_reg32( &global_regs->grxfsiz, 0x00000120 );
- dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100120 ); //ep0 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000130 ); //ep1 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00800230 ); //ep3 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x008002b0 ); //ep5 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[3], 0x00800330 ); //ep7 tx fifo
- dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[4], 0x001003b0 ); //ep9 tx fifo
+ dwc_write_reg32( &global_regs->grxfsiz, 0x00000120 );
+ dwc_write_reg32( &global_regs->gnptxfsiz, 0x00100120 ); //ep0 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[0], 0x01000130 ); //ep1 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[1], 0x00800230 ); //ep3 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[2], 0x008002b0 ); //ep5 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[3], 0x00800330 ); //ep7 tx fifo
+ dwc_write_reg32( &global_regs->dptxfsiz_dieptxf[4], 0x001003b0 ); //ep9 tx fifo
#endif
if(_core_if->en_multiple_tx_fifo && _core_if->dma_enable)
depctl.d32 = 0;
depctl.b.epdis = 1;
depctl.b.snak = 1;
- dwc_write_reg32( &dev_if->in_ep_regs[0]->diepctl, depctl.d32 );
- dwc_write_reg32( &dev_if->in_ep_regs[0]->dieptsiz, 0 );
- dwc_write_reg32( &dev_if->in_ep_regs[0]->diepdma, 0 );
- dwc_write_reg32( &dev_if->in_ep_regs[0]->diepint, 0xff );
+ dwc_write_reg32( &dev_if->in_ep_regs[0]->diepctl, depctl.d32 );
+ dwc_write_reg32( &dev_if->in_ep_regs[0]->dieptsiz, 0 );
+ dwc_write_reg32( &dev_if->in_ep_regs[0]->diepdma, 0 );
+ dwc_write_reg32( &dev_if->in_ep_regs[0]->diepint, 0xff );
- dwc_write_reg32( &dev_if->out_ep_regs[0]->doepctl, depctl.d32 );
- dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz, 0 );
- dwc_write_reg32( &dev_if->out_ep_regs[0]->doepdma, 0 );
- dwc_write_reg32( &dev_if->out_ep_regs[0]->doepint, 0xff );
+ dwc_write_reg32( &dev_if->out_ep_regs[0]->doepctl, depctl.d32 );
+ dwc_write_reg32( &dev_if->out_ep_regs[0]->doeptsiz, 0 );
+ dwc_write_reg32( &dev_if->out_ep_regs[0]->doepdma, 0 );
+ dwc_write_reg32( &dev_if->out_ep_regs[0]->doepint, 0xff );
depctl.d32 = 0;
depctl.b.setd0pid = 1;
- dwc_write_reg32( &dev_if->in_ep_regs[1]->diepctl, depctl.d32);
+ dwc_write_reg32( &dev_if->in_ep_regs[1]->diepctl, depctl.d32);
depctl.b.snak = 1;
depctl.b.txfnum = 2;
depctl.b.eptype = 2;
- depctl.b.usbactep = 1;
- depctl.b.mps = 0x200;
- dwc_write_reg32( &dev_if->out_ep_regs[2]->doepctl, depctl.d32 );
- dwc_write_reg32( &dev_if->out_ep_regs[2]->doepint, 0xff );
-
- /* global register initial */
- dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, 0x2f );//device IN interrutp mask
- dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, 0x0f );//device OUT interrutp mask
- dwc_write_reg32( &dev_if->dev_global_regs->daint, 0xffffffff ); //clear all pending intrrupt
- daintmsk.b.inep0 = 1;
- daintmsk.b.inep1 = 1;
- daintmsk.b.outep0 = 1;
- daintmsk.b.outep2 = 1;
- dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, daintmsk.d32 );
+ depctl.b.usbactep = 1;
+ depctl.b.mps = 0x200;
+ dwc_write_reg32( &dev_if->out_ep_regs[2]->doepctl, depctl.d32 );
+ dwc_write_reg32( &dev_if->out_ep_regs[2]->doepint, 0xff );
+
+ /* global register initial */
+ dwc_write_reg32( &dev_if->dev_global_regs->diepmsk, 0x2f );//device IN interrutp mask
+ dwc_write_reg32( &dev_if->dev_global_regs->doepmsk, 0x0f );//device OUT interrutp mask
+ dwc_write_reg32( &dev_if->dev_global_regs->daint, 0xffffffff ); //clear all pending intrrupt
+ daintmsk.b.inep0 = 1;
+ daintmsk.b.inep1 = 1;
+ daintmsk.b.outep0 = 1;
+ daintmsk.b.outep2 = 1;
+ dwc_write_reg32( &dev_if->dev_global_regs->daintmsk, daintmsk.d32 );
- dwc_write_reg32( &global_regs->gintsts, 0xffffffff );
- dwc_write_reg32( &global_regs->gotgint, 0xffffffff );
- dwc_otg_enable_device_interrupts(_core_if);
- gahbcfg.d32 = 0;
- gahbcfg.b.glblintrmsk = 1;
- gahbcfg.b.dmaenable = 1;
+ dwc_write_reg32( &global_regs->gintsts, 0xffffffff );
+ dwc_write_reg32( &global_regs->gotgint, 0xffffffff );
+ dwc_otg_enable_device_interrupts(_core_if);
+ gahbcfg.d32 = 0;
+ gahbcfg.b.glblintrmsk = 1;
+ gahbcfg.b.dmaenable = 1;
gahbcfg.b.hburstlen = DWC_GAHBCFG_INT_DMA_BURST_INCR16; // yk@20101221
- dwc_write_reg32( &global_regs->gahbcfg, gahbcfg.d32 );
+ dwc_write_reg32( &global_regs->gahbcfg, gahbcfg.d32 );
}
/**
#include "linux/dwc_otg_plat.h"
#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
#include "dwc_otg_attr.h"
#include "dwc_otg_driver.h"
#include "dwc_otg_cil.h"
dwc_otg_device_t* g_otgdev = NULL;
+extern struct dwc_otg_platform_data usb20otg_pdata;
+extern struct dwc_otg_platform_data usb20host_pdata;
/*-------------------------------------------------------------------------*/
/* Encapsulate the module parameter settings */
static DRIVER_ATTR(debuglevel, S_IRUGO|S_IWUSR, dbg_level_show, dbg_level_store);
#ifdef CONFIG_USB
-extern struct usb_hub *g_root_hub20;
+extern struct usb_hub *g_dwc_otg_root_hub20;
#ifdef DWC_BOTH_HOST_SLAVE
extern void hcd_start( dwc_otg_core_if_t *_core_if );
-extern void hub_disconnect_device(struct usb_hub *hub);
+extern void dwc_otg_hub_disconnect_device(struct usb_hub *hub);
static ssize_t force_usb_mode_show(struct device_driver *_drv, char *_buf)
{
printk("dwc_otg_force_device,already in B_PERIPHERAL,everest\n");
return;
}
- hub_disconnect_device(g_root_hub20);
+ dwc_otg_hub_disconnect_device(g_dwc_otg_root_hub20);
otg_dev->core_if->op_state = B_PERIPHERAL;
/* Reset the Controller */
dwc_otg_core_reset( core_if );
dwc_otg_force_device(core_if);
}
//if(dwc_otg_connid(core_if))
- // hub_disconnect_device();
+ // dwc_otg_hub_disconnect_device(g_dwc_otg_root_hub20);
//core_if->usb_mode = new_mode;
// dwc_otg_force_device(core_if);
}
return IRQ_RETVAL(retval);
}
+#ifdef CONFIG_USB20_OTG
/**
* This function is called when a lm_device is unregistered with the
* dwc_otg_driver. This happens, for example, when the rmmod command is
*
* @param[in] pdev platform_device definition
*/
-static __devinit int dwc_otg_driver_probe(struct platform_device *pdev)
+static int dwc_otg_driver_probe(struct platform_device *pdev)
{
- int retval = 0;
- struct resource *res_base;
- struct device *dev = &pdev->dev;
- dwc_otg_device_t *dwc_otg_device;
- int32_t snpsid;
- int irq;
- struct dwc_otg_platform_data *pldata = dev->platform_data;
+ struct device_node *node = pdev->dev.of_node;
+ int retval = 0;
+ struct resource *res_base;
+ struct device *dev = &pdev->dev;
+ dwc_otg_device_t *dwc_otg_device;
+ int32_t snpsid;
+ int irq;
+ struct dwc_otg_platform_data *pldata;
+
+ dev->platform_data = &usb20otg_pdata;
+ pldata = dev->platform_data;
+ pldata->dev = dev;
+
+ if (!node) {
+ dev_err(dev, "device node not found\n");
+ return -EINVAL;
+ }
- // clock and hw init
- if(pldata->hw_init)
- pldata->hw_init();
+ // clock and hw init
+ if(pldata->hw_init)
+ pldata->hw_init();
- if(pldata->clock_init){
- pldata->clock_init(pldata);
- pldata->clock_enable(pldata, 1);
- }
+ if(pldata->clock_init){
+ pldata->clock_init(pldata);
+ pldata->clock_enable(pldata, 1);
+ }
- if(pldata->phy_suspend)
- pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+ if(pldata->phy_suspend)
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
- if(pldata->soft_reset)
- pldata->soft_reset();
+ if(pldata->soft_reset)
+ pldata->soft_reset();
dwc_otg_device = kmalloc(sizeof(dwc_otg_device_t), GFP_KERNEL);
if (!res_base)
goto fail;
- dwc_otg_device->base = ioremap(res_base->start,res_base->end-res_base->start+1);
+ dwc_otg_device->base = devm_ioremap_resource(dev, res_base);
if (dwc_otg_device->base == NULL)
{
dev_err(dev, "ioremap() failed\n");
/*
* Create Device Attributes in sysfs
- */
+ */
dwc_otg_attr_create(dev);
#ifndef CONFIG_DWC_OTG_DEVICE_ONLY
retval |= device_create_file(dev, &dev_attr_enable);
* to this driver. The remove function is called when a device is
* unregistered with the bus driver.
*/
+static const struct of_device_id usb20_otg_of_match[] = {
+ { .compatible = "rockchip,usb20_otg", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, usb20_otg_of_match);
static struct platform_driver dwc_otg_driver = {
.probe = dwc_otg_driver_probe,
.remove = dwc_otg_driver_remove,
.shutdown = dwc_otg_driver_shutdown,
.driver = {
.name = dwc_driver_name,
- .owner = THIS_MODULE},
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(usb20_otg_of_match),
+ },
};
-
+#endif
#ifdef CONFIG_USB20_HOST
extern void dwc_otg_hcd_remove(struct device *dev);
-extern int __devinit host20_hcd_init(struct device *_dev);
+extern int host20_hcd_init(struct device *_dev);
static int host20_driver_remove(struct platform_device *pdev)
*
* @param[in] pdev platform_device definition
*/
-static __devinit int host20_driver_probe(struct platform_device *pdev)
+static int host20_driver_probe(struct platform_device *pdev)
{
- struct resource *res_base;
- int retval = 0;
- struct device *dev = &pdev->dev;
- dwc_otg_device_t *dwc_otg_device;
- int32_t snpsid;
- int irq;
- struct dwc_otg_platform_data *pldata = dev->platform_data;
-
- // clock and hw init
- if(pldata->hw_init)
- pldata->hw_init();
+ struct device_node *node = pdev->dev.of_node;
+ struct resource *res_base;
+ int retval = 0;
+ struct device *dev = &pdev->dev;
+ dwc_otg_device_t *dwc_otg_device;
+ int32_t snpsid;
+ int irq;
+ struct dwc_otg_platform_data *pldata;
+
+ dev->platform_data = &usb20host_pdata;
+ pldata = dev->platform_data;
+ pldata->dev = dev;
+
+ if (!node) {
+ dev_err(dev, "device node not found\n");
+ return -EINVAL;
+ }
+
+ // clock and hw init
+ if(pldata->hw_init)
+ pldata->hw_init();
- if(pldata->clock_init){
- pldata->clock_init(pldata);
- pldata->clock_enable(pldata, 1);
- }
+ if(pldata->clock_init){
+ pldata->clock_init(pldata);
+ pldata->clock_enable(pldata, 1);
+ }
- if(pldata->phy_suspend)
- pldata->phy_suspend(pldata, USB_PHY_ENABLED);
+ if(pldata->phy_suspend)
+ pldata->phy_suspend(pldata, USB_PHY_ENABLED);
- if(pldata->soft_reset)
- pldata->soft_reset();
+ if(pldata->soft_reset)
+ pldata->soft_reset();
/*
*Enable usb phy
if (!res_base)
goto fail;
- dwc_otg_device->base =
- ioremap(res_base->start,res_base->end-res_base->start+1);
- DWC_PRINT("%s host2.0 reg addr: 0x%x remap:0x%x\n",__func__,
+ dwc_otg_device->base = devm_ioremap_resource(dev, res_base);
+ DWC_PRINT("%s host2.0 reg addr: 0x%x remap:0x%x\n",__func__,
(unsigned)res_base->start, (unsigned)dwc_otg_device->base);
if (dwc_otg_device->base == NULL)
{
return retval;
}
+static const struct of_device_id usb20_host_of_match[] = {
+ { .compatible = "rockchip,usb20_host", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, usb20_host_of_match);
static struct platform_driver host20_driver = {
.probe = host20_driver_probe,
.remove = host20_driver_remove,
.driver = {
.name = "usb20_host",
- .owner = THIS_MODULE},
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(usb20_host_of_match),
+ },
};
#endif
/*
* USB2.0 OTG controller
*/
+#ifdef CONFIG_USB20_OTG
retval = platform_driver_register(&dwc_otg_driver);
if (retval < 0)
{
#endif
#ifdef CONFIG_RK_USB_UART
-if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart))
- pr_warning("DWC_OTG: Failed to create driver dwc_otg_force_uart file");
-#endif
+ if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart))
+ pr_warning("DWC_OTG: Failed to create driver dwc_otg_force_uart file");
+#endif
+
#ifndef CONFIG_DWC_OTG_HOST_ONLY
if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_vbus_status))
pr_warning("DWC_OTG: Failed to create driver vbus status file");
#endif
+
#ifdef DWC_BOTH_HOST_SLAVE
if(driver_create_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode))
pr_warning("DWC_OTG: Failed to create driver force usb mode file\n");
#endif
-
+
+#endif
+
/*
* USB2.0 host controller
*/
{
DWC_PRINT("dwc_otg_driver_cleanup()\n");
+#ifdef CONFIG_USB20_OTG
driver_remove_file(&dwc_otg_driver.driver, &driver_attr_version);
driver_remove_file(&dwc_otg_driver.driver, &driver_attr_debuglevel);
#ifdef DWC_BOTH_HOST_SLAVE
- driver_remove_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode);
+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_force_usb_mode);
#endif
+
#ifndef CONFIG_DWC_OTG_HOST_ONLY
- driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_conn_en);
+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_conn_en);
#endif
#ifdef CONFIG_RK_USB_UART
- driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart);
+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_dwc_otg_force_uart);
#endif
#ifndef CONFIG_DWC_OTG_HOST_ONLY
- driver_remove_file(&dwc_otg_driver.driver, &driver_attr_vbus_status);
+ driver_remove_file(&dwc_otg_driver.driver, &driver_attr_vbus_status);
#endif
platform_driver_unregister(&dwc_otg_driver);
+#endif
#ifdef CONFIG_USB11_HOST
platform_driver_unregister(&host11_driver);
-#include <linux/kernel.h>\r
-#include <linux/platform_device.h>\r
-#include <linux/delay.h>\r
-#include <linux/dma-mapping.h>\r
-#include <linux/clk.h>\r
-\r
-#include <mach/irqs.h>\r
-#include <mach/gpio.h>\r
-#include <mach/iomux.h>\r
-#include <mach/cru.h>\r
-\r
-#include "usbdev_rk.h"\r
-#include "dwc_otg_regs.h" \r
-\r
-#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188)\r
-\r
-#define GRF_REG_BASE RK30_GRF_BASE \r
-#define USBOTG_SIZE RK30_USBOTG20_SIZE\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
-#define USBGRF_SOC_STATUS0 (GRF_REG_BASE+0xac)\r
-#define USBGRF_UOC0_CON0 (GRF_REG_BASE+0x10c)\r
-#define USBGRF_UOC0_CON2 (GRF_REG_BASE+0x114)\r
-#define USBGRF_UOC0_CON3 (GRF_REG_BASE+0x118)\r
-#define USBGRF_UOC1_CON0 (GRF_REG_BASE+0x11C)\r
-#define USBGRF_UOC1_CON2 (GRF_REG_BASE+0x124)\r
-#define USBGRF_UOC1_CON3 (GRF_REG_BASE+0x128)\r
-#define USBGRF_UOC3_CON0 (GRF_REG_BASE+0x138)\r
-\r
-#define USBGRF_UOC2_CON0 (GRF_REG_BASE+0x12C)\r
-#if defined(CONFIG_SOC_RK3066B) || defined(CONFIG_SOC_RK3108) \r
-#define RK3066B_HOST_DRV_VBUS RK30_PIN0_PD7\r
-#define RK3066B_OTG_DRV_VBUS RK30_PIN0_PD6\r
-#elif defined(CONFIG_SOC_RK3168) || defined(CONFIG_SOC_RK3188) || defined(CONFIG_SOC_RK3168M) || defined(CONFIG_SOC_RK3188M)\r
-#define RK3066B_HOST_DRV_VBUS RK30_PIN0_PC0\r
-#define RK3066B_OTG_DRV_VBUS RK30_PIN3_PD5\r
-#elif defined(CONFIG_SOC_RK3028)\r
-#define RK3066B_HOST_DRV_VBUS RK30_PIN1_PA4\r
-#define RK3066B_OTG_DRV_VBUS RK30_PIN3_PD7\r
-#endif\r
-\r
-#else\r
-#define USBGRF_SOC_STATUS0 (GRF_REG_BASE+0x15c)\r
-#define USBGRF_UOC0_CON2 (GRF_REG_BASE+0x184)\r
-#define USBGRF_UOC1_CON2 (GRF_REG_BASE+0x190)\r
-#endif\r
-\r
-int dwc_otg_check_dpdm(void)\r
-{\r
- static uint8_t * reg_base = 0;\r
- volatile unsigned int * otg_dctl;\r
- volatile unsigned int * otg_gotgctl;\r
- volatile unsigned int * otg_hprt0;\r
- int bus_status = 0;\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);\r
- \r
- // softreset & clockgate \r
- *(unsigned int*)(RK30_CRU_BASE+0x120) = ((7<<5)<<16)|(7<<5); // otg0 phy clkgate\r
- udelay(3);\r
- *(unsigned int*)(RK30_CRU_BASE+0x120) = ((7<<5)<<16)|(0<<5); // otg0 phy clkgate\r
- dsb();\r
- *(unsigned int*)(RK30_CRU_BASE+0xd4) = ((1<<5)<<16); // otg0 phy clkgate\r
- *(unsigned int*)(RK30_CRU_BASE+0xe4) = ((1<<13)<<16); // otg0 hclk clkgate\r
- *(unsigned int*)(RK30_CRU_BASE+0xe0) = ((3<<5)<<16); // hclk usb clkgate\r
- \r
- // exit phy suspend \r
- *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.\r
- \r
- // soft connect\r
- if(reg_base == 0){\r
- reg_base = ioremap(RK30_USBOTG20_PHYS,USBOTG_SIZE);\r
- if(!reg_base){\r
- bus_status = -1;\r
- goto out;\r
- }\r
- }\r
- mdelay(105);\r
- printk("regbase %p 0x%x, otg_phy_con%p, 0x%x\n",\r
- reg_base, *(reg_base), otg_phy_con1, *otg_phy_con1);\r
- otg_dctl = (unsigned int * )(reg_base+0x804);\r
- otg_gotgctl = (unsigned int * )(reg_base);\r
- otg_hprt0 = (unsigned int * )(reg_base + DWC_OTG_HOST_PORT_REGS_OFFSET);\r
- if(*otg_gotgctl &(1<<19)){\r
- bus_status = 1;\r
- *otg_dctl &= ~2;\r
- mdelay(50); // delay about 10ms\r
- // check dp,dm\r
- if((*otg_hprt0 & 0xc00)==0xc00)\r
- bus_status = 2;\r
- }\r
-out:\r
- return bus_status;\r
-}\r
-\r
-EXPORT_SYMBOL(dwc_otg_check_dpdm);\r
-\r
-#ifdef CONFIG_USB20_OTG\r
-/*DWC_OTG*/\r
-static struct resource usb20_otg_resource[] = {\r
- {\r
- .start = IRQ_USB_OTG,\r
- .end = IRQ_USB_OTG,\r
- .flags = IORESOURCE_IRQ,\r
- },\r
- {\r
- .start = RK30_USBOTG20_PHYS,\r
- .end = RK30_USBOTG20_PHYS + RK30_USBOTG20_SIZE - 1,\r
- .flags = IORESOURCE_MEM,\r
- },\r
-\r
-};\r
-\r
-void usb20otg_hw_init(void)\r
-{\r
-#ifndef CONFIG_USB20_HOST\r
- // close USB 2.0 HOST phy and clock\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2);\r
- unsigned int * otg_phy_con2 = (unsigned int*)(USBGRF_UOC1_CON3);\r
- *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); //enable soft control\r
- *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend \r
-#else\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2);\r
- *otg_phy_con1 = 0x554|(0xfff<<16); // enter suspend.\r
-#endif\r
-#endif\r
- // usb phy config init\r
-#ifdef CONFIG_ARCH_RK3188\r
- //usb phy enter usb mode\r
- unsigned int * otg_phy_con3 = (unsigned int*)(USBGRF_UOC0_CON0);\r
- *otg_phy_con3 = (0x0300 << 16);\r
- //Disconnect Threshold Adjustment\r
- *otg_phy_con3 = (0x07<<1)|((0x07<<1)<<16); \r
-#endif \r
- // other haredware init\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- //GPIO init\r
- gpio_request(RK3066B_OTG_DRV_VBUS, NULL);\r
- gpio_direction_output(RK3066B_OTG_DRV_VBUS, GPIO_LOW);\r
-#else\r
- rk30_mux_api_set(GPIO0A5_OTGDRVVBUS_NAME, GPIO0A_OTG_DRV_VBUS);\r
-#endif\r
-}\r
-\r
-void usb20otg_phy_suspend(void* pdata, int suspend)\r
-{\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);\r
- unsigned int * otg_phy_con2 = (unsigned int*)(USBGRF_UOC0_CON3);\r
- if(suspend){\r
- *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); ; //enable soft control\r
- *otg_phy_con2 = 0x2A|(0x3F<<16);; // enter suspend\r
- usbpdata->phy_status = 1;\r
- }\r
- else{\r
- *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.\r
- usbpdata->phy_status = 0;\r
- }\r
-#else\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON2);\r
- if(suspend){\r
- *otg_phy_con1 = 0x554|(0xfff<<16); // enter suspend.\r
- usbpdata->phy_status = 1;\r
- }\r
- else{\r
- *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.\r
- usbpdata->phy_status = 0;\r
- }\r
-#endif\r
-}\r
-void usb20otg_soft_reset(void)\r
-{\r
- cru_set_soft_reset(SOFT_RST_USBOTG0, true);\r
- cru_set_soft_reset(SOFT_RST_USBPHY0, true);\r
- cru_set_soft_reset(SOFT_RST_OTGC0, true);\r
- udelay(1);\r
-\r
- cru_set_soft_reset(SOFT_RST_USBOTG0, false);\r
- cru_set_soft_reset(SOFT_RST_USBPHY0, false);\r
- cru_set_soft_reset(SOFT_RST_OTGC0, false);\r
- mdelay(1);\r
-}\r
-void usb20otg_clock_init(void* pdata)\r
-{\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- struct clk* ahbclk,*phyclk;\r
- ahbclk = clk_get(NULL, "hclk_otg0");\r
- phyclk = clk_get(NULL, "otgphy0");\r
- usbpdata->phyclk = phyclk;\r
- usbpdata->ahbclk = ahbclk;\r
-}\r
-void usb20otg_clock_enable(void* pdata, int enable)\r
-{\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
-\r
- if(enable){\r
- clk_enable(usbpdata->ahbclk);\r
- clk_enable(usbpdata->phyclk);\r
- }\r
- else{\r
- clk_disable(usbpdata->phyclk);\r
- clk_disable(usbpdata->ahbclk);\r
- }\r
-}\r
-int usb20otg_get_status(int id)\r
-{\r
- int ret = -1;\r
- unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);\r
- switch(id)\r
- {\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- case USB_STATUS_BVABLID:\r
- // bvalid in grf\r
- ret = (usbgrf_status &(1<<10));\r
- break;\r
- case USB_STATUS_DPDM:\r
- // dpdm in grf\r
- ret = (usbgrf_status &(3<<11));\r
- break;\r
- case USB_STATUS_ID:\r
- // id in grf\r
- ret = (usbgrf_status &(1<<13));\r
- break;\r
-#else\r
- case USB_STATUS_BVABLID:\r
- // bvalid in grf\r
- ret = (usbgrf_status &0x20000);\r
- break;\r
- case USB_STATUS_DPDM:\r
- // dpdm in grf\r
- ret = (usbgrf_status &(3<<18));\r
- break;\r
- case USB_STATUS_ID:\r
- // id in grf\r
- ret = (usbgrf_status &(1<<20));\r
- break;\r
-#endif\r
- default:\r
- break;\r
- }\r
- return ret;\r
-}\r
-\r
-#ifdef CONFIG_RK_USB_UART\r
-void dwc_otg_uart_mode(void* pdata, int enter_usb_uart_mode)\r
-{\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC0_CON0);\r
- \r
- if(1 == enter_usb_uart_mode){ //enter uart mode\r
- /*note: can't disable otg here! If otg disable, the ID change\r
- *interrupt can't be triggered when otg cable connect without\r
- *device.At the same time, uart can't be used normally \r
- */\r
- //*otg_phy_con1 = (0x10 | (0x10 << 16));//otg disable\r
- *otg_phy_con1 = (0x0300 | (0x0300 << 16));//bypass dm \r
- }\r
- if(0 == enter_usb_uart_mode){ //enter usb mode \r
- *otg_phy_con1 = (0x0300 << 16); //bypass dm disable\r
- //*otg_phy_con1 = (0x10 << 16);//otg enable \r
- }\r
-}\r
-#endif\r
-\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
-void usb20otg_power_enable(int enable)\r
-{ \r
- unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);\r
- if(0 == enable)//disable\r
- {\r
- gpio_set_value(RK3066B_OTG_DRV_VBUS, GPIO_LOW); \r
-\r
- }\r
- if(1 == enable)//enable\r
- {\r
- gpio_set_value(RK3066B_OTG_DRV_VBUS, GPIO_HIGH); \r
- } \r
-}\r
-#endif\r
-struct dwc_otg_platform_data usb20otg_pdata = {\r
- .phyclk = NULL,\r
- .ahbclk = NULL,\r
- .busclk = NULL,\r
- .phy_status = 0,\r
- .hw_init=usb20otg_hw_init,\r
- .phy_suspend=usb20otg_phy_suspend,\r
- .soft_reset=usb20otg_soft_reset,\r
- .clock_init=usb20otg_clock_init,\r
- .clock_enable=usb20otg_clock_enable,\r
- .get_status=usb20otg_get_status,\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- .power_enable=usb20otg_power_enable,\r
-#endif\r
-#ifdef CONFIG_RK_USB_UART\r
- .dwc_otg_uart_mode=dwc_otg_uart_mode,\r
-#endif\r
-};\r
-\r
-struct platform_device device_usb20_otg = {\r
- .name = "usb20_otg",\r
- .id = -1,\r
- .num_resources = ARRAY_SIZE(usb20_otg_resource),\r
- .resource = usb20_otg_resource,\r
- .dev = {\r
- .platform_data = &usb20otg_pdata,\r
- },\r
-};\r
-#endif\r
-#ifdef CONFIG_USB20_HOST\r
-static struct resource usb20_host_resource[] = {\r
- {\r
- .start = IRQ_USB_HOST,\r
- .end = IRQ_USB_HOST,\r
- .flags = IORESOURCE_IRQ,\r
- },\r
- {\r
- .start = RK30_USBHOST20_PHYS,\r
- .end = RK30_USBHOST20_PHYS + RK30_USBHOST20_SIZE - 1,\r
- .flags = IORESOURCE_MEM,\r
- },\r
-\r
-};\r
-void usb20host_hw_init(void)\r
-{\r
- // usb phy config init\r
-#ifdef CONFIG_ARCH_RK3188\r
- //Disconnect Threshold Adjustment\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON0);\r
- *otg_phy_con1 = (0x07<<1)|((0x07<<1)<<16);\r
-#endif \r
-\r
- // other haredware init\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- gpio_request(RK3066B_HOST_DRV_VBUS, NULL);\r
- gpio_direction_output(RK3066B_HOST_DRV_VBUS, GPIO_HIGH);\r
-#else\r
- rk30_mux_api_set(GPIO0A6_HOSTDRVVBUS_NAME, GPIO0A_HOST_DRV_VBUS);\r
-#endif\r
-}\r
-void usb20host_phy_suspend(void* pdata, int suspend)\r
-{ \r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2);\r
- unsigned int * otg_phy_con2 = (unsigned int*)(USBGRF_UOC1_CON3);\r
- if(suspend)\r
- {\r
- *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); ; //enable soft control\r
- *otg_phy_con2 = 0x2A|(0x3F<<16);; // enter suspend\r
- usbpdata->phy_status = 1;\r
- }\r
- else\r
- {\r
- *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.\r
- usbpdata->phy_status = 0;\r
- } \r
-#else\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- unsigned int * otg_phy_con1 = (unsigned int*)(USBGRF_UOC1_CON2);\r
- if(suspend)\r
- {\r
- *otg_phy_con1 = 0x554|(0xfff<<16); // enter suspend.\r
- usbpdata->phy_status = 1;\r
- }\r
- else\r
- {\r
- *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.\r
- usbpdata->phy_status = 0;\r
- }\r
-#endif \r
-}\r
-void usb20host_soft_reset(void)\r
-{\r
- cru_set_soft_reset(SOFT_RST_USBOTG1, true);\r
- cru_set_soft_reset(SOFT_RST_USBPHY1, true);\r
- cru_set_soft_reset(SOFT_RST_OTGC1, true);\r
- udelay(5);\r
-\r
- cru_set_soft_reset(SOFT_RST_USBOTG1, false);\r
- cru_set_soft_reset(SOFT_RST_USBPHY1, false);\r
- cru_set_soft_reset(SOFT_RST_OTGC1, false);\r
- mdelay(2);\r
-}\r
-void usb20host_clock_init(void* pdata)\r
-{\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- struct clk* ahbclk,*phyclk;\r
- ahbclk = clk_get(NULL, "hclk_otg1");\r
- phyclk = clk_get(NULL, "otgphy1");\r
- usbpdata->phyclk = phyclk;\r
- usbpdata->ahbclk = ahbclk;\r
-}\r
-void usb20host_clock_enable(void* pdata, int enable)\r
-{\r
- struct dwc_otg_platform_data *usbpdata=pdata;\r
- \r
- if(enable){\r
- clk_enable(usbpdata->ahbclk);\r
- clk_enable(usbpdata->phyclk);\r
- }\r
- else{\r
- clk_disable(usbpdata->phyclk);\r
- clk_disable(usbpdata->ahbclk);\r
- }\r
-}\r
-int usb20host_get_status(int id)\r
-{\r
- int ret = -1;\r
- unsigned int usbgrf_status = *(unsigned int*)(USBGRF_SOC_STATUS0);\r
- switch(id)\r
- {\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- case USB_STATUS_BVABLID:\r
- // bvalid in grf\r
- ret = (usbgrf_status &(1<<17));\r
- break;\r
- case USB_STATUS_DPDM:\r
- // dpdm in grf\r
- ret = (usbgrf_status &(3<<18));\r
- break;\r
- case USB_STATUS_ID:\r
- // id in grf\r
- ret = (usbgrf_status &(1<<20));\r
- break;\r
-#else\r
- case USB_STATUS_BVABLID:\r
- // bvalid in grf\r
- ret = (usbgrf_status &(1<<22));\r
- break;\r
- case USB_STATUS_DPDM:\r
- // dpdm in grf\r
- ret = (usbgrf_status &(3<<23));\r
- break;\r
- case USB_STATUS_ID:\r
- // id in grf\r
- ret = 0;\r
- break;\r
-#endif\r
- default:\r
- break;\r
- }\r
- return ret;\r
-}\r
-\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
-void usb20host_power_enable(int enable)\r
-{ \r
-\r
- if(0 == enable)//disable\r
- {\r
- //ret = gpio_request(RK3066B_HOST_DRV_VBUS, NULL);\r
- //if (ret != 0) {\r
- // gpio_free(RK3066B_HOST_DRV_VBUS);\r
- //}\r
- //gpio_direction_output(RK3066B_HOST_DRV_VBUS, 1);\r
- //gpio_set_value(RK3066B_HOST_DRV_VBUS, 0);\r
- //printk("!!!!!!!!!!!!!!!!!!!disable host power!!!!!!!!!!!!!!!!!!\n");\r
- }\r
-\r
- if(1 == enable)//enable\r
- {\r
- gpio_set_value(RK3066B_HOST_DRV_VBUS, GPIO_HIGH);\r
- //printk("!!!!!!!!!!!!!!!!!!!!!enable host power!!!!!!!!!!!!!!!!!!\n");\r
- } \r
-}\r
-#endif\r
-struct dwc_otg_platform_data usb20host_pdata = {\r
- .phyclk = NULL,\r
- .ahbclk = NULL,\r
- .busclk = NULL,\r
- .phy_status = 0,\r
- .hw_init=usb20host_hw_init,\r
- .phy_suspend=usb20host_phy_suspend,\r
- .soft_reset=usb20host_soft_reset,\r
- .clock_init=usb20host_clock_init,\r
- .clock_enable=usb20host_clock_enable,\r
- .get_status=usb20host_get_status,\r
-#if defined(CONFIG_ARCH_RK3066B) || defined(CONFIG_ARCH_RK3188)\r
- .power_enable=usb20host_power_enable,\r
-#endif \r
-};\r
-\r
-struct platform_device device_usb20_host = {\r
- .name = "usb20_host",\r
- .id = -1,\r
- .num_resources = ARRAY_SIZE(usb20_host_resource),\r
- .resource = usb20_host_resource,\r
- .dev = {\r
- .platform_data = &usb20host_pdata,\r
- },\r
-};\r
-#endif\r
-#ifdef CONFIG_USB_EHCI_RK\r
-void rkehci_hw_init(void)\r
-{\r
- unsigned int * phy_con0 = (unsigned int*)(USBGRF_UOC2_CON0);\r
- unsigned int * phy_con1 = (unsigned int*)(USBGRF_UOC1_CON0);\r
- unsigned int * phy_con2 = (unsigned int*)(USBGRF_UOC0_CON0);\r
- unsigned int * phy_con3 = (unsigned int*)(USBGRF_UOC3_CON0);\r
- // usb phy config init\r
- // hsic phy config init, set hsicphy_txsrtune\r
- *phy_con0 = ((0xf<<6)<<16)|(0xf<<6);\r
-\r
- // other haredware init\r
- // set common_on, in suspend mode, otg/host PLL blocks remain powered\r
-#ifdef CONFIG_ARCH_RK3188\r
- *phy_con1 = (1<<16)|0;\r
-#else\r
- *phy_con2 = (1<<16)|0;\r
-#endif\r
- /* change INCR to INCR16 or INCR8(beats less than 16)\r
- * or INCR4(beats less than 8) or SINGLE(beats less than 4)\r
- */\r
- *phy_con3 = 0x00ff00bc;\r
-}\r
-\r
-void rkehci_clock_init(void* pdata)\r
-{\r
- struct rkehci_platform_data *usbpdata=pdata;\r
-\r
-#ifdef CONFIG_ARCH_RK3188 \r
- struct clk *clk_otg, *clk_hs;\r
-\r
- /* By default, hsicphy_480m's parent is otg phy 480MHz clk\r
- * rk3188 must use host phy 480MHz clk\r
- */\r
- clk_hs = clk_get(NULL, "hsicphy_480m");\r
- clk_otg = clk_get(NULL, "otgphy1_480m");\r
- clk_set_parent(clk_hs, clk_otg);\r
-#endif\r
-\r
- usbpdata->hclk_hsic = clk_get(NULL, "hclk_hsic");\r
- usbpdata->hsic_phy_480m = clk_get(NULL, "hsicphy_480m");\r
- usbpdata->hsic_phy_12m = clk_get(NULL, "hsicphy_12m");\r
-}\r
-\r
-void rkehci_clock_enable(void* pdata, int enable)\r
-{\r
- struct rkehci_platform_data *usbpdata=pdata;\r
-\r
- if(enable == usbpdata->clk_status)\r
- return;\r
-\r
- if(enable){\r
- clk_enable(usbpdata->hclk_hsic);\r
- clk_enable(usbpdata->hsic_phy_480m);\r
- clk_enable(usbpdata->hsic_phy_12m);\r
- usbpdata->clk_status = 1;\r
- }else{\r
- clk_disable(usbpdata->hsic_phy_12m);\r
- clk_disable(usbpdata->hsic_phy_480m);\r
- clk_disable(usbpdata->hclk_hsic);\r
- usbpdata->clk_status = 0;\r
- }\r
-}\r
-\r
-void rkehci_soft_reset(void)\r
-{\r
- unsigned int * phy_con0 = (unsigned int*)(USBGRF_UOC2_CON0);\r
-\r
- cru_set_soft_reset(SOFT_RST_HSICPHY, true);\r
- udelay(12);\r
- cru_set_soft_reset(SOFT_RST_HSICPHY, false);\r
- mdelay(2);\r
-\r
- *phy_con0 = ((1<<10)<<16)|(1<<10);\r
- udelay(2);\r
- *phy_con0 = ((1<<10)<<16)|(0<<10);\r
- udelay(2);\r
-\r
- cru_set_soft_reset(SOFT_RST_HSIC_AHB, true);\r
- udelay(2);\r
- cru_set_soft_reset(SOFT_RST_HSIC_AHB, false);\r
- udelay(2);\r
-}\r
-\r
-struct rkehci_platform_data rkehci_pdata = {\r
- .hclk_hsic = NULL,\r
- .hsic_phy_12m = NULL,\r
- .hsic_phy_480m = NULL,\r
- .clk_status = -1,\r
- .hw_init = rkehci_hw_init,\r
- .clock_init = rkehci_clock_init,\r
- .clock_enable = rkehci_clock_enable,\r
- .soft_reset = rkehci_soft_reset,\r
-};\r
-\r
-static struct resource resources_hsusb_host[] = {\r
- {\r
- .start = IRQ_HSIC,\r
- .end = IRQ_HSIC,\r
- .flags = IORESOURCE_IRQ,\r
- },\r
- {\r
- .start = RK30_HSIC_PHYS,\r
- .end = RK30_HSIC_PHYS + RK30_HSIC_SIZE - 1,\r
- .flags = IORESOURCE_MEM,\r
- },\r
-};\r
-\r
-struct platform_device device_hsusb_host = {\r
- .name = "rk_hsusb_host",\r
- .id = -1,\r
- .num_resources = ARRAY_SIZE(resources_hsusb_host),\r
- .resource = resources_hsusb_host,\r
- .dev = {\r
- .coherent_dma_mask = 0xffffffff,\r
- .platform_data = &rkehci_pdata,\r
- },\r
-};\r
-#endif\r
-\r
-static int __init usbdev_init_devices(void)\r
-{\r
-#ifdef CONFIG_USB_EHCI_RK\r
- platform_device_register(&device_hsusb_host);\r
-#endif\r
-#ifdef CONFIG_USB20_OTG\r
- platform_device_register(&device_usb20_otg);\r
-#endif\r
-#ifdef CONFIG_USB20_HOST\r
- platform_device_register(&device_usb20_host);\r
-#endif\r
- return 0;\r
-}\r
-arch_initcall(usbdev_init_devices);\r
-#endif\r
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include "usbdev_rk.h"
+#include "dwc_otg_regs.h"
+
+static struct dwc_otg_control_usb *control_usb;
+
+int dwc_otg_check_dpdm(void)
+{
+ int bus_status = 0;
+ return bus_status;
+}
+
+EXPORT_SYMBOL(dwc_otg_check_dpdm);
+
+#ifdef CONFIG_USB20_OTG
+
+void usb20otg_hw_init(void)
+{
+#ifndef CONFIG_USB20_HOST
+ unsigned int * otg_phy_con1 = (control_usb->grf_uoc1_base + 0x8);
+ unsigned int * otg_phy_con2 = (control_usb->grf_uoc1_base + 0xc);
+ *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); //enable soft control
+ *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend
+#endif
+ /* usb phy config init
+ * usb phy enter usb mode */
+ unsigned int * otg_phy_con3 = (control_usb->grf_uoc0_base);
+ *otg_phy_con3 = (0x0300 << 16);
+
+ /* other haredware init,include:
+ * DRV_VBUS GPIO init */
+ gpio_direction_output(control_usb->otg_gpios->gpio, 0);
+}
+
+void usb20otg_phy_suspend(void* pdata, int suspend)
+{
+ struct dwc_otg_platform_data *usbpdata=pdata;
+ unsigned int * otg_phy_con1 = (control_usb->grf_uoc0_base + 0x8);
+ unsigned int * otg_phy_con2 = (control_usb->grf_uoc0_base + 0xc);
+
+ if(suspend){
+ *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); //enable soft control
+ *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend
+ usbpdata->phy_status = 1;
+ }else{
+ *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.
+ usbpdata->phy_status = 0;
+ }
+}
+
+void usb20otg_soft_reset(void)
+{
+}
+
+void usb20otg_clock_init(void* pdata)
+{
+ /*
+ struct dwc_otg_platform_data *usbpdata=pdata;
+ struct clk* ahbclk,*phyclk;
+
+ ahbclk = devm_clk_get(usbpdata->dev, "hclk_otg0");
+ if (IS_ERR(ahbclk)) {
+ dev_err(usbpdata->dev, "Failed to get hclk_otg0\n");
+ return;
+ }
+
+ phyclk = devm_clk_get(usbpdata->dev, "otgphy0");
+ if (IS_ERR(phyclk)) {
+ dev_err(usbpdata->dev, "Failed to get otgphy0\n");
+ return;
+ }
+
+ usbpdata->phyclk = phyclk;
+ usbpdata->ahbclk = ahbclk;*/
+}
+
+void usb20otg_clock_enable(void* pdata, int enable)
+{
+ /*
+ struct dwc_otg_platform_data *usbpdata=pdata;
+
+ if(enable){
+ clk_prepare_enable(usbpdata->ahbclk);
+ clk_prepare_enable(usbpdata->phyclk);
+ }else{
+ clk_disable_unprepare(usbpdata->ahbclk);
+ clk_disable_unprepare(usbpdata->phyclk);
+ }
+ */
+}
+
+int usb20otg_get_status(int id)
+{
+ int ret = -1;
+ unsigned int usbgrf_status = *(unsigned int*)(control_usb->grf_soc_status0);
+
+ switch(id){
+ case USB_STATUS_BVABLID:
+ // bvalid in grf
+ ret = (usbgrf_status &(1<<10));
+ break;
+ case USB_STATUS_DPDM:
+ // dpdm in grf
+ ret = (usbgrf_status &(3<<11));
+ break;
+ case USB_STATUS_ID:
+ // id in grf
+ ret = (usbgrf_status &(1<<13));
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+#ifdef CONFIG_RK_USB_UART
+void dwc_otg_uart_mode(void* pdata, int enter_usb_uart_mode)
+{
+ unsigned int * otg_phy_con1 = (unsigned int*)(control_usb->grf_uoc0_base);
+
+ if(1 == enter_usb_uart_mode){
+ /* enter uart mode
+ * note: can't disable otg here! If otg disable, the ID change
+ * interrupt can't be triggered when otg cable connect without
+ * device.At the same time, uart can't be used normally
+ */
+ *otg_phy_con1 = (0x0300 | (0x0300 << 16)); //bypass dm
+ }else if(0 == enter_usb_uart_mode){
+ /* enter usb mode */
+ *otg_phy_con1 = (0x0300 << 16); //bypass dm disable
+ }
+}
+#endif
+
+void usb20otg_power_enable(int enable)
+{
+ if(0 == enable){//disable otg_drv power
+ gpio_set_value(control_usb->otg_gpios->gpio, 0);
+ }else if(1 == enable){//enable otg_drv power
+ gpio_set_value(control_usb->otg_gpios->gpio, 1);
+ }
+}
+
+struct dwc_otg_platform_data usb20otg_pdata = {
+ .phyclk = NULL,
+ .ahbclk = NULL,
+ .busclk = NULL,
+ .phy_status = 0,
+ .hw_init=usb20otg_hw_init,
+ .phy_suspend=usb20otg_phy_suspend,
+ .soft_reset=usb20otg_soft_reset,
+ .clock_init=usb20otg_clock_init,
+ .clock_enable=usb20otg_clock_enable,
+ .get_status=usb20otg_get_status,
+ .power_enable=usb20otg_power_enable,
+#ifdef CONFIG_RK_USB_UART
+ .dwc_otg_uart_mode=dwc_otg_uart_mode,
+#endif
+};
+
+#endif
+
+#ifdef CONFIG_USB20_HOST
+void usb20host_hw_init(void)
+{
+ /* usb phy config init */
+
+ /* other haredware init,include:
+ * DRV_VBUS GPIO init */
+ gpio_direction_output(control_usb->host_gpios->gpio, 1);
+
+}
+
+void usb20host_phy_suspend(void* pdata, int suspend)
+{
+ struct dwc_otg_platform_data *usbpdata=pdata;
+ unsigned int * otg_phy_con1 = (unsigned int*)(control_usb->grf_uoc1_base + 0x8);
+ unsigned int * otg_phy_con2 = (unsigned int*)(control_usb->grf_uoc1_base + 0xc);
+
+ if(suspend){
+ *otg_phy_con1 = (0x01<<2)|((0x01<<2)<<16); // enable soft control
+ *otg_phy_con2 = 0x2A|(0x3F<<16); // enter suspend
+ usbpdata->phy_status = 1;
+ }else{
+ *otg_phy_con1 = ((0x01<<2)<<16); // exit suspend.
+ usbpdata->phy_status = 0;
+ }
+}
+
+void usb20host_soft_reset(void)
+{
+}
+
+void usb20host_clock_init(void* pdata)
+{
+ /*
+ struct dwc_otg_platform_data *usbpdata=pdata;
+ struct clk* ahbclk,*phyclk;
+
+ ahbclk = devm_clk_get(usbpdata->dev, "hclk_otg1");
+ if (IS_ERR(ahbclk)) {
+ dev_err(usbpdata->dev, "Failed to get hclk_otg1\n");
+ return;
+ }
+
+ phyclk = devm_clk_get(usbpdata->dev, "otgphy1");
+ if (IS_ERR(phyclk)) {
+ dev_err(usbpdata->dev, "Failed to get otgphy1\n");
+ return;
+ }
+
+ usbpdata->phyclk = phyclk;
+ usbpdata->ahbclk = ahbclk;*/
+}
+
+void usb20host_clock_enable(void* pdata, int enable)
+{
+ /*
+ struct dwc_otg_platform_data *usbpdata=pdata;
+
+ if(enable){
+ clk_prepare_enable(usbpdata->ahbclk);
+ clk_prepare_enable(usbpdata->phyclk);
+ }else{
+ clk_disable_unprepare(usbpdata->ahbclk);
+ clk_disable_unprepare(usbpdata->phyclk);
+ }*/
+}
+
+int usb20host_get_status(int id)
+{
+ int ret = -1;
+ unsigned int usbgrf_status = *(unsigned int*)(control_usb->grf_soc_status0);
+
+ switch(id){
+ case USB_STATUS_BVABLID:
+ // bvalid in grf
+ ret = (usbgrf_status &(1<<17));
+ break;
+ case USB_STATUS_DPDM:
+ // dpdm in grf
+ ret = (usbgrf_status &(3<<18));
+ break;
+ case USB_STATUS_ID:
+ // id in grf
+ ret = (usbgrf_status &(1<<20));
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+void usb20host_power_enable(int enable)
+{
+ if(0 == enable){//disable host_drv power
+ //do not disable power in default
+ }else if(1 == enable){//enable host_drv power
+ gpio_set_value(control_usb->host_gpios->gpio, 1);
+ }
+}
+
+struct dwc_otg_platform_data usb20host_pdata = {
+ .phyclk = NULL,
+ .ahbclk = NULL,
+ .busclk = NULL,
+ .phy_status = 0,
+ .hw_init=usb20host_hw_init,
+ .phy_suspend=usb20host_phy_suspend,
+ .soft_reset=usb20host_soft_reset,
+ .clock_init=usb20host_clock_init,
+ .clock_enable=usb20host_clock_enable,
+ .get_status=usb20host_get_status,
+ .power_enable=usb20host_power_enable,
+};
+#endif
+
+static int dwc_otg_control_usb_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ int gpio, err;
+ struct device_node *np = pdev->dev.of_node;
+
+ control_usb = devm_kzalloc(&pdev->dev, sizeof(*control_usb),GFP_KERNEL);
+ if (!control_usb) {
+ dev_err(&pdev->dev, "unable to alloc memory for control usb\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "GRF_SOC_STATUS0");
+ control_usb->grf_soc_status0 = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_usb->grf_soc_status0))
+ return PTR_ERR(control_usb->grf_soc_status0);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "GRF_UOC0_BASE");
+ control_usb->grf_uoc0_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_usb->grf_uoc0_base))
+ return PTR_ERR(control_usb->grf_uoc0_base);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "GRF_UOC1_BASE");
+ control_usb->grf_uoc1_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(control_usb->grf_uoc1_base))
+ return PTR_ERR(control_usb->grf_uoc1_base);
+
+ control_usb->host_gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
+
+ gpio = of_get_named_gpio(np, "gpios", 0);
+ if(!gpio_is_valid(gpio)){
+ dev_err(&pdev->dev, "invalid host gpio%d\n", gpio);
+ return -EINVAL;
+ }
+ control_usb->host_gpios->gpio = gpio;
+ err = devm_gpio_request(&pdev->dev, gpio, "host_drv_gpio");
+ if (err) {
+ dev_err(&pdev->dev,
+ "failed to request GPIO%d for host_drv\n",
+ gpio);
+ return err;
+ }
+
+ control_usb->otg_gpios = devm_kzalloc(&pdev->dev, sizeof(struct gpio), GFP_KERNEL);
+
+ gpio = of_get_named_gpio(np, "gpios", 1);
+ if(!gpio_is_valid(gpio)){
+ dev_err(&pdev->dev, "invalid otg gpio%d\n", gpio);
+ return -EINVAL;
+ }
+ control_usb->otg_gpios->gpio = gpio;
+ err = devm_gpio_request(&pdev->dev, gpio, "otg_drv_gpio");
+ if (err) {
+ dev_err(&pdev->dev,
+ "failed to request GPIO%d for otg_drv\n",
+ gpio);
+ return err;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id dwc_otg_control_usb_id_table[] = {
+ { .compatible = "rockchip,dwc-control-usb" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, dwc_otg_control_usb_id_table);
+#endif
+
+static struct platform_driver dwc_otg_control_usb_driver = {
+ .probe = dwc_otg_control_usb_probe,
+ .driver = {
+ .name = "dwc-control-usb",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(dwc_otg_control_usb_id_table),
+ },
+};
+
+static int __init dwc_otg_control_usb_init(void)
+{
+ return platform_driver_register(&dwc_otg_control_usb_driver);
+}
+subsys_initcall(dwc_otg_control_usb_init);
+
+static void __exit dwc_otg_control_usb_exit(void)
+{
+ platform_driver_unregister(&dwc_otg_control_usb_driver);
+}
+
+module_exit(dwc_otg_control_usb_exit);
+MODULE_ALIAS("platform: dwc_control_usb");
+MODULE_AUTHOR("RockChip Inc.");
+MODULE_DESCRIPTION("RockChip Control Module USB Driver");
+MODULE_LICENSE("GPL v2");