/***************************************************************************** ** FILE NAME : dwc_otg_ifx.c ** PROJECT : USB Host and Device driver ** MODULES : USB Host and Device driver ** SRC VERSION : 2.0 ** DATE : 1/March/2008 ** AUTHOR : Chen, Howard based on Synopsys Original ** DESCRIPTION : Platform specific initialization ** FUNCTIONS : ** COMPILER : gcc ** REFERENCE : ** COPYRIGHT : ** Version Control Section ** ** $Author$ ** $Date$ ** $Revisions$ ** $Log$ Revision history *****************************************************************************/ /*! \file dwc_otg_ifx.c \brief Platform specific initialization. */ #include #include "ifxusb_version.h" #include "dwc_otg_ifx.h" #include "dwc_otg_plat.h" extern int dwc_core_num; #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) #include #include #include #endif #if defined(CONFIG_TWINPASS) || defined(CONFIG_AMAZON_S) #if defined(CONFIG_AMAZON_S_DSL_AFE_API) || defined(CONFIG_AMAZON_S_DSL_AFE_API_MODULE) extern void ifx_enable_afe_oc(void); #define ifx_usb_enable_afe_oc ifx_enable_afe_oc #else void ifx_usb_enable_afe_oc(void); #endif #endif #if defined(CONFIG_TWINPASS) || defined(CONFIG_DANUBE) void dwc_otg_power_on (void) { // set clock gating set_bit (4, (volatile unsigned long *)DANUBE_CGU_IFCCR); set_bit (5, (volatile unsigned long *)DANUBE_CGU_IFCCR); MDELAY(100); // set power clear_bit (0, (volatile unsigned long *)DANUBE_PMU_PWDCR);//PHY clear_bit (6, (volatile unsigned long *)DANUBE_PMU_PWDCR);//USB clear_bit (9, (volatile unsigned long *)DANUBE_PMU_PWDCR);//DSL clear_bit (15, (volatile unsigned long *)DANUBE_PMU_PWDCR);//AHB #if defined(CONFIG_TWINPASS) ifx_usb_enable_afe_oc(); #endif // PHY configurations. dwc_write_reg32 ( (volatile uint32_t *)0xbe10103c,0x14014); } void dwc_otg_power_off (void) { // set power set_bit (0, (volatile unsigned long *)DANUBE_PMU_PWDCR);//PHY set_bit (6, (volatile unsigned long *)DANUBE_PMU_PWDCR);//USB } void dwc_otg_ahb_reset (void) { set_bit (6, DANUBE_RCU_RESET); MDELAY(100); clear_bit (6, DANUBE_RCU_RESET); MDELAY(100); } void dwc_otg_hard_reset (void) { #if defined (DWC_IS_HOST) // make the hardware be a host controller (default) clear_bit (DANUBE_USBCFG_HDSEL_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG); #elif defined (DWC_IS_DEVICE) /* set the controller to the device mode */ set_bit (DANUBE_USBCFG_HDSEL_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG); #else #error "For Danube/Twinpass, it should be HOST or Device Only." #endif // set the HC's byte-order to big-endian set_bit (DANUBE_USBCFG_HOST_END_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG); clear_bit (DANUBE_USBCFG_SLV_END_BIT, (volatile unsigned long *)DANUBE_RCU_USBCFG); set_bit (4, DANUBE_RCU_RESET); MDELAY(500); clear_bit (4, DANUBE_RCU_RESET); MDELAY(500); #if defined(CONFIG_TWINPASS) ifx_usb_enable_afe_oc(); #endif // PHY configurations. dwc_write_reg32 ( (volatile uint32_t *)0xbe10103c,0x14014); } int dwc_otg_vbus=0; //extern void usb_set_vbus_on(); //extern void usb_set_vbus_off(); void dwc_otg_vbus_on (void) { dwc_otg_vbus=1; printk(KERN_INFO "SENDING VBus POWER UP\n"); // usb_set_vbus_on(); } void dwc_otg_vbus_off (void) { dwc_otg_vbus=0; printk(KERN_INFO "SENDING VBus POWER DOWN\n"); // usb_set_vbus_off(); } //int dwc_otg_vbus_status (void) //{ // return dwc_otg_vbus; //} #elif defined(CONFIG_AMAZON_SE) void dwc_otg_power_on (void) { // set clock gating // clear_bit (4, (volatile unsigned long *)AMAZON_SE_CGU_IFCCR); clear_bit (5, (volatile unsigned long *)AMAZON_SE_CGU_IFCCR); MDELAY(100); // set power clear_bit (0, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR); clear_bit (6, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR); clear_bit (9, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR); clear_bit (15, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR); // PHY configurations. dwc_write_reg32 ( (volatile uint32_t *)0xbe10103c,0x14014); } void dwc_otg_power_off (void) { // set power set_bit (0, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);//PHY set_bit (6, (volatile unsigned long *)AMAZON_SE_PMU_PWDCR);//USB } void dwc_otg_ahb_reset (void) { set_bit (6, AMAZON_SE_RCU_RESET); MDELAY(100); clear_bit (6, AMAZON_SE_RCU_RESET); MDELAY(100); } void dwc_otg_hard_reset (void) { #if defined (DWC_IS_HOST) // make the hardware be a host controller (default) clear_bit (AMAZON_SE_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG); #elif defined (DWC_IS_DEVICE) /* set the controller to the device mode */ set_bit (AMAZON_SE_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG); #else #error "For Danube/Twinpass, it should be HOST or Device Only." #endif // set the HC's byte-order to big-endian set_bit (AMAZON_SE_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG); clear_bit (AMAZON_SE_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_SE_RCU_USBCFG); set_bit (4, AMAZON_SE_RCU_RESET); MDELAY(500); clear_bit (4, AMAZON_SE_RCU_RESET); MDELAY(500); // PHY configurations. dwc_write_reg32 ( (volatile uint32_t *)0xbe10103c,0x14014); } void dwc_otg_vbus_on (void) { set_bit (4, (volatile unsigned long *)AMAZON_SE_GPIO_P0_OUT); } void dwc_otg_vbus_off (void) { clear_bit (4, (volatile unsigned long *)AMAZON_SE_GPIO_P0_OUT); } //int dwc_otg_vbus_status (void) //{ // if((readl((volatile uint32_t *)AMAZON_SE_GPIO_P0_OUT)&0x00000010)) // if(get_bit (4, (volatile unsigned long *)AMAZON_SE_GPIO_P0_OUT)) // return 1; // return 0; //} #elif defined(CONFIG_AMAZON_S) void dwc_otg_power_on (void) { // set clock gating set_bit (0, (volatile unsigned long *)AMAZON_S_CGU_IFCCR); set_bit (1, (volatile unsigned long *)AMAZON_S_CGU_IFCCR); // set power if(dwc_core_num==1){ clear_bit (26, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY clear_bit (27, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB } else{ clear_bit (0, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY clear_bit (6, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB } clear_bit (9, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//DSL clear_bit (15, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//AHB // Set Arbiter set_bit (AMAZON_S_USBCFG_ARB, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG); #if defined(CONFIG_AMAZON_S_DSL_AFE_API) || defined(CONFIG_AMAZON_S_DSL_AFE_API_MODULE) // AFE driver will initialize OC setting in AFE directly, USB driver only required registering IRQ handller // remove duplicate called. // ifx_usb_enable_afe_oc(); #endif // PHY configurations. if(dwc_core_num==1) dwc_write_reg32 ( (volatile uint32_t *)0xbe10603c,0x14014); else dwc_write_reg32 ( (volatile uint32_t *)0xbe10103c,0x14014); } void dwc_otg_power_off (void) { if(dwc_core_num==1){ set_bit (26, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY set_bit (27, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB } else{ set_bit (0, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//PHY set_bit (6, (volatile unsigned long *)AMAZON_S_PMU_PWDCR);//USB } } void dwc_otg_ahb_reset (void) { set_bit (6, (volatile unsigned long *)AMAZON_S_RCU_RST_REQ); MDELAY(100); clear_bit (6, (volatile unsigned long *)AMAZON_S_RCU_RST_REQ); MDELAY(100); } void dwc_otg_hard_reset (void) { #if defined (DWC_IS_HOST) if(dwc_core_num==1) clear_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG); else clear_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG); #elif defined (DWC_IS_DEVICE) if(dwc_core_num==1) set_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG); else set_bit (AMAZON_S_USBCFG_HDSEL_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG); #else #error "It should be HOST or Device Only." #endif // set the HC's byte-order to big-endian if(dwc_core_num==1){ set_bit (AMAZON_S_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG); clear_bit (AMAZON_S_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB2CFG); } else{ set_bit (AMAZON_S_USBCFG_HOST_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG); clear_bit (AMAZON_S_USBCFG_SLV_END_BIT, (volatile unsigned long *)AMAZON_S_RCU_USB1CFG); } if(dwc_core_num==1){ set_bit (28, (volatile unsigned long *)AMAZON_S_RCU_USBRESET); MDELAY(500); clear_bit (28, (volatile unsigned long *)AMAZON_S_RCU_USBRESET); MDELAY(500); } else{ set_bit (4, (volatile unsigned long *)AMAZON_S_RCU_USBRESET); MDELAY(500); clear_bit (4, (volatile unsigned long *)AMAZON_S_RCU_USBRESET); MDELAY(500); } // PHY configurations. if(dwc_core_num==1) dwc_write_reg32 ( (volatile uint32_t *)0xbe10603c,0x14014); else dwc_write_reg32 ( (volatile uint32_t *)0xbe10103c,0x14014); } void dwc_otg_vbus_on (void) { #ifdef DWC_IS_HOST if(dwc_core_num==0) { if (bsp_port_reserve_pin(1, 13, PORT_MODULE_USB) != 0) { printk(KERN_ERR "Can't enable USB1 5.5V power via P1.13 (GPIO29)!!\n"); return; } bsp_port_clear_altsel0(1, 13, PORT_MODULE_USB); bsp_port_clear_altsel1(1, 13, PORT_MODULE_USB); bsp_port_set_dir_out(1, 13, PORT_MODULE_USB); bsp_port_set_output(1, 13, PORT_MODULE_USB); bsp_port_set_open_drain(1, 13, PORT_MODULE_USB); printk(KERN_ERR "Enable USB1 power via P1.13 (GPIO29)!!\n"); } else { if (bsp_port_reserve_pin(3, 4, PORT_MODULE_USB) != 0) { printk(KERN_ERR "Can't enable USB2 5.5V power!!\n"); return; } bsp_port_clear_altsel0(3, 4, PORT_MODULE_USB); bsp_port_clear_altsel1(3, 4, PORT_MODULE_USB); bsp_port_set_dir_out(3, 4, PORT_MODULE_USB); bsp_port_set_output(3, 4, PORT_MODULE_USB); bsp_port_set_open_drain(3, 4, PORT_MODULE_USB); printk(KERN_ERR "Enable USB2 power via P3.4 (GPIO52)!!\n"); } #endif } void dwc_otg_vbus_off (void) { #ifdef DWC_IS_HOST if(dwc_core_num==0) { bsp_port_set_output(1, 13, PORT_MODULE_USB); printk(KERN_ERR "Disable USB1 power!!\n"); } else { bsp_port_set_output(3, 4, PORT_MODULE_USB); printk(KERN_ERR "Disable USB2 power!!\n"); } #endif } #else // CONFIG_AMAZON_S #error "Please choose one platform!!" #endif // CONFIG #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) static void release_platform_dev(struct device * dev) { printk("IFX dwc_otg USB platform_dev release\n"); dev->parent = NULL; } static struct resource resources[] = { [0] = { // .name = "irq" // .start = IFX_USB_IRQ, .flags = IORESOURCE_IRQ, }, [1] = { // .name = "address", // .start = IFX_USB_IOMEM_BASE, // .end = IFX_USB_IOMEM_BASE+REGSIZE, .flags = IORESOURCE_MEM, }, [2] = { // .name = "address", .start = IFX_USB_FIFOMEM_BASE, .end = IFX_USB_FIFOMEM_BASE+IFX_USB_FIFOMEM_SIZE, .flags = IORESOURCE_MEM, }, }; static u64 dwc_dmamask = (u32)0x1fffffff; static struct platform_device platform_dev = { .id = -1, .dev = { .release = release_platform_dev, .dma_mask = &dwc_dmamask, }, .resource = resources, .num_resources = ARRAY_SIZE(resources), }; extern const char dwc_driver_name[]; int ifx_usb_hc_init(unsigned long base_addr, int irq) { if (platform_dev.dev.parent) return -EBUSY; /* finish seting up the platform device */ resources[0].start = irq; resources[1].start = base_addr; resources[1].end = base_addr + REGSIZE; /* The driver core will probe for us. We know sl811-hcd has been * initialized already because of the link order dependency. */ platform_dev.name = dwc_driver_name; return platform_device_register(&platform_dev); } void ifx_usb_hc_remove(void) { platform_device_unregister(&platform_dev); } #endif #if defined(CONFIG_TWINPASS) #define ADSL_BASE 0x20000 #define CRI_BASE 0x31F00 #define CRI_CCR0 CRI_BASE + 0x00 #define CRI_CCR1 CRI_BASE + 0x01*4 #define CRI_CDC0 CRI_BASE + 0x02*4 #define CRI_CDC1 CRI_BASE + 0x03*4 #define CRI_RST CRI_BASE + 0x04*4 #define CRI_MASK0 CRI_BASE + 0x05*4 #define CRI_MASK1 CRI_BASE + 0x06*4 #define CRI_MASK2 CRI_BASE + 0x07*4 #define CRI_STATUS0 CRI_BASE + 0x08*4 #define CRI_STATUS1 CRI_BASE + 0x09*4 #define CRI_STATUS2 CRI_BASE + 0x0A*4 #define CRI_AMASK0 CRI_BASE + 0x0B*4 #define CRI_AMASK1 CRI_BASE + 0x0C*4 #define CRI_UPDCTL CRI_BASE + 0x0D*4 #define CRI_MADST CRI_BASE + 0x0E*4 // 0x0f is missing #define CRI_EVENT0 CRI_BASE + 0x10*4 #define CRI_EVENT1 CRI_BASE + 0x11*4 #define CRI_EVENT2 CRI_BASE + 0x12*4 #define IRI_I_ENABLE 0x32000 #define STY_SMODE 0x3c004 #define AFE_TCR_0 0x3c0dc #define AFE_ADDR_ADDR 0x3c0e8 #define AFE_RDATA_ADDR 0x3c0ec #define AFE_WDATA_ADDR 0x3c0f0 #define AFE_CONFIG 0x3c0f4 #define AFE_SERIAL_CFG 0x3c0fc #define DFE_BASE_ADDR 0xBE116000 //#define DFE_BASE_ADDR 0x9E116000 #define MEI_FR_ARCINT_C (DFE_BASE_ADDR + 0x0000001C) #define MEI_DBG_WADDR_C (DFE_BASE_ADDR + 0x00000024) #define MEI_DBG_RADDR_C (DFE_BASE_ADDR + 0x00000028) #define MEI_DBG_DATA_C (DFE_BASE_ADDR + 0x0000002C) #define MEI_DBG_DECO_C (DFE_BASE_ADDR + 0x00000030) #define MEI_DBG_MASTER_C (DFE_BASE_ADDR + 0x0000003C) static void WriteARCmem(uint32_t addr, uint32_t data) { writel(1 ,(volatile uint32_t *)MEI_DBG_MASTER_C); writel(1 ,(volatile uint32_t *)MEI_DBG_DECO_C ); writel(addr ,(volatile uint32_t *)MEI_DBG_WADDR_C ); writel(data ,(volatile uint32_t *)MEI_DBG_DATA_C ); while( (dwc_read_reg32((volatile uint32_t *)MEI_FR_ARCINT_C) & 0x20) != 0x20 ){}; writel(0 ,(volatile uint32_t *)MEI_DBG_MASTER_C); printk(KERN_INFO "WriteARCmem %08x %08x\n",addr,data); }; static uint32_t ReadARCmem(uint32_t addr) { u32 data; writel(1 ,(volatile uint32_t *)MEI_DBG_MASTER_C); writel(1 ,(volatile uint32_t *)MEI_DBG_DECO_C ); writel(addr ,(volatile uint32_t *)MEI_DBG_RADDR_C ); while( (dwc_read_reg32((volatile uint32_t *)MEI_FR_ARCINT_C) & 0x20) != 0x20 ){}; data = dwc_read_reg32((volatile uint32_t *)MEI_DBG_DATA_C ); writel(0 ,(volatile uint32_t *)MEI_DBG_MASTER_C); printk(KERN_INFO "ReadARCmem %08x %08x\n",addr,data); return data; }; void ifx_usb_enable_afe_oc(void) { /* Start the clock */ WriteARCmem(CRI_UPDCTL ,0x00000008); WriteARCmem(CRI_CCR0 ,0x00000014); WriteARCmem(CRI_CCR1 ,0x00000500); WriteARCmem(AFE_CONFIG ,0x000001c8); WriteARCmem(AFE_SERIAL_CFG,0x00000016); // (DANUBE_PCI_CFG_BASE+(1<