1ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss/* 2ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * USB block power/access management abstraction. 3ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * 4ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * Au1000+: The OHCI block control register is at the far end of the OHCI memory 5ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * area. Au1550 has OHCI on different base address. No need to handle 6ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * UDC here. 7ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * Au1200: one register to control access and clocks to O/EHCI, UDC and OTG 8ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * as well as the PHY for EHCI and UDC. 9ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * 10ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss */ 11ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 12ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#include <linux/init.h> 13ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#include <linux/io.h> 14ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#include <linux/module.h> 15ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#include <linux/spinlock.h> 16ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#include <linux/syscore_ops.h> 17ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#include <asm/mach-au1x00/au1000.h> 18ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 19ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss/* control register offsets */ 20ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define AU1000_OHCICFG 0x7fffc 21ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define AU1550_OHCICFG 0x07ffc 22ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define AU1200_USBCFG 0x04 23ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 24ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss/* Au1000 USB block config bits */ 25ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBHEN_RD (1 << 4) /* OHCI reset-done indicator */ 26ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBHEN_CE (1 << 3) /* OHCI block clock enable */ 27ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBHEN_E (1 << 2) /* OHCI block enable */ 28ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBHEN_C (1 << 1) /* OHCI block coherency bit */ 29ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBHEN_BE (1 << 0) /* OHCI Big-Endian */ 30ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 31ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss/* Au1200 USB config bits */ 32ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_PFEN (1 << 31) /* prefetch enable (undoc) */ 33ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_RDCOMB (1 << 30) /* read combining (undoc) */ 34ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_UNKNOWN (5 << 20) /* unknown, leave this way */ 35ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_SSD (1 << 23) /* serial short detect en */ 36ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_PPE (1 << 19) /* HS PHY PLL */ 37ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_UCE (1 << 18) /* UDC clock enable */ 38ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_ECE (1 << 17) /* EHCI clock enable */ 39ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_OCE (1 << 16) /* OHCI clock enable */ 40ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_FLA(x) (((x) & 0x3f) << 8) 41ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_UCAM (1 << 7) /* coherent access (undoc) */ 42ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_GME (1 << 6) /* OTG mem access */ 43ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_DBE (1 << 5) /* UDC busmaster enable */ 44ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_DME (1 << 4) /* UDC mem enable */ 45ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_EBE (1 << 3) /* EHCI busmaster enable */ 46ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_EME (1 << 2) /* EHCI mem enable */ 47ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_OBE (1 << 1) /* OHCI busmaster enable */ 48ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_OME (1 << 0) /* OHCI mem enable */ 49ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#define USBCFG_INIT_AU1200 (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\ 50ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \ 51ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss USBCFG_GME | USBCFG_DBE | USBCFG_DME | \ 52ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \ 53ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss USBCFG_OME) 54ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 55809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss/* Au1300 USB config registers */ 56809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL1 0x00 57809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL2 0x04 58809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_VBUS_TIMER 0x10 59809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_SBUS_CTRL 0x14 60809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_MSR_ERR 0x18 61809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL3 0x1C 62809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL4 0x20 63809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_OTG_STATUS 0x28 64809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL5 0x2C 65809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL6 0x30 66809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL7 0x34 67809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_PHY_STATUS 0xC0 68809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INT_STATUS 0xC4 69809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INT_ENABLE 0xC8 70809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 71809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */ 72809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */ 73809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */ 74809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 75809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */ 76809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */ 77809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */ 78809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 79809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19) 80809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18) 81809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17) 82809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_DWC_CTRL3_OTG0_CKEN (1 << 16) 83809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 84809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */ 85809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 86809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INTEN_FORCE 0x20 87809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INTEN_PHY 0x10 88809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INTEN_UDC 0x08 89809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INTEN_EHCI 0x04 90809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INTEN_OHCI1 0x02 91809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss#define USB_INTEN_OHCI0 0x01 92ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 93ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic DEFINE_SPINLOCK(alchemy_usb_lock); 94ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 95809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline void __au1300_usb_phyctl(void __iomem *base, int enable) 96809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 97809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss unsigned long r, s; 98809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 99809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL2); 100809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss s = __raw_readl(base + USB_DWC_CTRL3); 101809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 102809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN | 103809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN; 104809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 105809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (enable) { 106809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss /* simply enable all PHYs */ 107809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS | 108809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss USB_DWC_CTRL2_PHYRS; 109809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL2); 110809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 111809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } else if (!s) { 112809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss /* no USB block active, do disable all PHYs */ 113809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS | 114809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss USB_DWC_CTRL2_PHYRS); 115809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL2); 116809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 117809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 118809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 119809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 120809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline void __au1300_ohci_control(void __iomem *base, int enable, int id) 121809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 122809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss unsigned long r; 123809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 124809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (enable) { 125809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */ 126809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 127809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 128809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */ 129809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN 130809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss : USB_DWC_CTRL3_OHCI1_CKEN; 131809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL3); 132809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 133809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 134809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); /* power up the PHYs */ 135809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 136809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_INT_ENABLE); 137809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1; 138809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_INT_ENABLE); 139809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 140809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 141809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss /* reset the OHCI start clock bit */ 142809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(0, base + USB_DWC_CTRL7); 143809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 144809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } else { 145809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_INT_ENABLE); 146809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1); 147809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_INT_ENABLE); 148809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 149809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 150809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL3); 151809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN 152809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss : USB_DWC_CTRL3_OHCI1_CKEN); 153809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL3); 154809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 155809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 156809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 157809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 158809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 159809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 160809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline void __au1300_ehci_control(void __iomem *base, int enable) 161809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 162809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss unsigned long r; 163809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 164809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (enable) { 165809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL3); 166809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_DWC_CTRL3_EHCI0_CKEN; 167809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL3); 168809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 169809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 170809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL1); 171809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_DWC_CTRL1_HSTRS; 172809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL1); 173809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 174809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 175809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 176809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 177809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_INT_ENABLE); 178809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_INTEN_EHCI; 179809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_INT_ENABLE); 180809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 181809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } else { 182809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_INT_ENABLE); 183809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_INTEN_EHCI; 184809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_INT_ENABLE); 185809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 186809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 187809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL1); 188809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_DWC_CTRL1_HSTRS; 189809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL1); 190809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 191809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 192809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL3); 193809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_DWC_CTRL3_EHCI0_CKEN; 194809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL3); 195809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 196809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 197809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 198809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 199809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 200809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 201809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline void __au1300_udc_control(void __iomem *base, int enable) 202809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 203809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss unsigned long r; 204809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 205809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (enable) { 206809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL1); 207809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_DWC_CTRL1_DCRS; 208809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL1); 209809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 210809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 211809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 212809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 213809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_INT_ENABLE); 214809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_INTEN_UDC; 215809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_INT_ENABLE); 216809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 217809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } else { 218809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_INT_ENABLE); 219809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_INTEN_UDC; 220809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_INT_ENABLE); 221809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 222809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 223809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL1); 224809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_DWC_CTRL1_DCRS; 225809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL1); 226809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 227809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 228809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 229809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 230809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 231809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 232809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline void __au1300_otg_control(void __iomem *base, int enable) 233809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 234809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss unsigned long r; 235809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (enable) { 236809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL3); 237809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_DWC_CTRL3_OTG0_CKEN; 238809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL3); 239809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 240809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 241809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL1); 242809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_DWC_CTRL1_OTGD; 243809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL1); 244809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 245809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 246809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 247809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } else { 248809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL1); 249809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r |= USB_DWC_CTRL1_OTGD; 250809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL1); 251809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 252809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 253809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r = __raw_readl(base + USB_DWC_CTRL3); 254809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss r &= ~USB_DWC_CTRL3_OTG0_CKEN; 255809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(r, base + USB_DWC_CTRL3); 256809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 257809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 258809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_usb_phyctl(base, enable); 259809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 260809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 261809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 262809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline int au1300_usb_control(int block, int enable) 263809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 264809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss void __iomem *base = 265809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); 266809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss int ret = 0; 267809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 268809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss switch (block) { 269809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_USB_OHCI0: 270809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_ohci_control(base, enable, 0); 271809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 272809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_USB_OHCI1: 273809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_ohci_control(base, enable, 1); 274809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 275809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_USB_EHCI0: 276809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_ehci_control(base, enable); 277809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 278809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_USB_UDC0: 279809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_udc_control(base, enable); 280809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 281809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_USB_OTG0: 282809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __au1300_otg_control(base, enable); 283809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 284809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss default: 285809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss ret = -ENODEV; 286809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 287809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss return ret; 288809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 289809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 290809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic inline void au1300_usb_init(void) 291809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 292809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss void __iomem *base = 293809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); 294809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 295809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss /* set some sane defaults. Note: we don't fiddle with DWC_CTRL4 296809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss * here at all: Port 2 routing (EHCI or UDC) must be set either 297809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss * by boot firmware or platform init code; I can't autodetect 298809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss * a sane setting. 299809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss */ 300809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */ 301809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 302809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */ 303809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 304809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */ 305809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 306809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */ 307809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 308809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss /* set coherent access bit */ 309809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL); 310809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 311809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 312ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 313ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline void __au1200_ohci_control(void __iomem *base, int enable) 314ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 315ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss unsigned long r = __raw_readl(base + AU1200_USBCFG); 316ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (enable) { 317ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG); 318ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 319ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(2000); 320ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } else { 321ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG); 322ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 323ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 324ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 325ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 326ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 327ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline void __au1200_ehci_control(void __iomem *base, int enable) 328ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 329ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss unsigned long r = __raw_readl(base + AU1200_USBCFG); 330ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (enable) { 331ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG); 332ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 333ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 334ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } else { 335ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (!(r & USBCFG_UCE)) /* UDC also off? */ 336ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */ 337ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG); 338ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 339ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 340ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 341ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 342ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 343ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline void __au1200_udc_control(void __iomem *base, int enable) 344ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 345ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss unsigned long r = __raw_readl(base + AU1200_USBCFG); 346ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (enable) { 347ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG); 348ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 349ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } else { 350ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (!(r & USBCFG_ECE)) /* EHCI also off? */ 351ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */ 352ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG); 353ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 354ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 355ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 356ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 357ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline int au1200_coherency_bug(void) 358ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 359ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#if defined(CONFIG_DMA_COHERENT) 360ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* Au1200 AB USB does not support coherent memory */ 361ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (!(read_c0_prid() & 0xff)) { 362ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss printk(KERN_INFO "Au1200 USB: this is chip revision AB !!\n"); 363ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss printk(KERN_INFO "Au1200 USB: update your board or re-configure" 364ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss " the kernel\n"); 365ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return -ENODEV; 366ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 367ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#endif 368ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return 0; 369ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 370ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 371ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline int au1200_usb_control(int block, int enable) 372ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 373ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss void __iomem *base = 374ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); 375ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss int ret = 0; 376ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 377ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss switch (block) { 378ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_USB_OHCI0: 379ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = au1200_coherency_bug(); 380ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (ret && enable) 381ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss goto out; 382ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __au1200_ohci_control(base, enable); 383ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 384ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_USB_UDC0: 385ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __au1200_udc_control(base, enable); 386ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 387ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_USB_EHCI0: 388ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = au1200_coherency_bug(); 389ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (ret && enable) 390ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss goto out; 391ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __au1200_ehci_control(base, enable); 392ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 393ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss default: 394ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = -ENODEV; 395ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 396ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussout: 397ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return ret; 398ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 399ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 400ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 401ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss/* initialize USB block(s) to a known working state */ 402ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline void au1200_usb_init(void) 403ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 404ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss void __iomem *base = 405ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR); 406ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG); 407ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 408ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 409ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 410ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 411ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline void au1000_usb_init(unsigned long rb, int reg) 412ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 413ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg); 414ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss unsigned long r = __raw_readl(base); 415ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 416ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#if defined(__BIG_ENDIAN) 417ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss r |= USBHEN_BE; 418ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss#endif 419ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss r |= USBHEN_C; 420ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 421ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r, base); 422ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 423ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 424ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 425ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 426ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 427ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg) 428ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 429ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss void __iomem *base = (void __iomem *)KSEG1ADDR(rb); 430ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss unsigned long r = __raw_readl(base + creg); 431ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 432ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (enable) { 433ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r | USBHEN_CE, base + creg); 434ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 435ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 436ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg); 437ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 438ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 439ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 440ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* wait for reset complete (read reg twice: au1500 erratum) */ 441ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss while (__raw_readl(base + creg), 442ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss !(__raw_readl(base + creg) & USBHEN_RD)) 443ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss udelay(1000); 444ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } else { 445ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg); 446ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 447ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 448ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 449ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 450ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic inline int au1000_usb_control(int block, int enable, unsigned long rb, 451ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss int creg) 452ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 453ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss int ret = 0; 454ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 455ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss switch (block) { 456ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_USB_OHCI0: 457ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __au1xx0_ohci_control(enable, rb, creg); 458ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 459ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss default: 460ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = -ENODEV; 461ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 462ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return ret; 463ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 464ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 465ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss/* 466ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * alchemy_usb_control - control Alchemy on-chip USB blocks 467ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * @block: USB block to target 468ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss * @enable: set 1 to enable a block, 0 to disable 469ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss */ 470ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussint alchemy_usb_control(int block, int enable) 471ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 472ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss unsigned long flags; 473ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss int ret; 474ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 475ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss spin_lock_irqsave(&alchemy_usb_lock, flags); 476ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss switch (alchemy_get_cputype()) { 477ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1000: 478ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1500: 479ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1100: 480ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = au1000_usb_control(block, enable, 481ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); 482ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 483ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1550: 484ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = au1000_usb_control(block, enable, 485ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); 486ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 487ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1200: 488ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = au1200_usb_control(block, enable); 489ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 490809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_CPU_AU1300: 491809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss ret = au1300_usb_control(block, enable); 492809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 493ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss default: 494ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss ret = -ENODEV; 495ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 496ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss spin_unlock_irqrestore(&alchemy_usb_lock, flags); 497ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return ret; 498ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 499ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel LaussEXPORT_SYMBOL_GPL(alchemy_usb_control); 500ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 501ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 502ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic unsigned long alchemy_usb_pmdata[2]; 503ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 504ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic void au1000_usb_pm(unsigned long br, int creg, int susp) 505ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 506ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss void __iomem *base = (void __iomem *)KSEG1ADDR(br); 507ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 508ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (susp) { 509ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss alchemy_usb_pmdata[0] = __raw_readl(base + creg); 510ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* There appears to be some undocumented reset register.... */ 511ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(0, base + 0x04); 512ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 513ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(0, base + creg); 514ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 515ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } else { 516ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(alchemy_usb_pmdata[0], base + creg); 517ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 518ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 519ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 520ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 521ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic void au1200_usb_pm(int susp) 522ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 523ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss void __iomem *base = 524ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR); 525ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss if (susp) { 526ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* save OTG_CAP/MUX registers which indicate port routing */ 527ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* FIXME: write an OTG driver to do that */ 528ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss alchemy_usb_pmdata[0] = __raw_readl(base + 0x00); 529ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss alchemy_usb_pmdata[1] = __raw_readl(base + 0x04); 530ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } else { 531ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* restore access to all MMIO areas */ 532ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1200_usb_init(); 533ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 534ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss /* restore OTG_CAP/MUX registers */ 535ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(alchemy_usb_pmdata[0], base + 0x00); 536ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss __raw_writel(alchemy_usb_pmdata[1], base + 0x04); 537ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss wmb(); 538ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 539ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 540ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 541809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Laussstatic void au1300_usb_pm(int susp) 542809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss{ 543809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss void __iomem *base = 544809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR); 545809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss /* remember Port2 routing */ 546809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss if (susp) { 547809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4); 548809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } else { 549809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss au1300_usb_init(); 550809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4); 551809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss wmb(); 552809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss } 553809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss} 554809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss 555ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic void alchemy_usb_pm(int susp) 556ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 557ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss switch (alchemy_get_cputype()) { 558ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1000: 559ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1500: 560ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1100: 561ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp); 562ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 563ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1550: 564ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp); 565ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 566ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1200: 567ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1200_usb_pm(susp); 568ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 569809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_CPU_AU1300: 570809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss au1300_usb_pm(susp); 571809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 572ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 573ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 574ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 575ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic int alchemy_usb_suspend(void) 576ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 577ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss alchemy_usb_pm(1); 578ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return 0; 579ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 580ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 581ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic void alchemy_usb_resume(void) 582ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 583ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss alchemy_usb_pm(0); 584ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 585ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 586ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic struct syscore_ops alchemy_usb_pm_ops = { 587ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss .suspend = alchemy_usb_suspend, 588ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss .resume = alchemy_usb_resume, 589ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss}; 590ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 591ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussstatic int __init alchemy_usb_init(void) 592ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss{ 593ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss switch (alchemy_get_cputype()) { 594ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1000: 595ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1500: 596ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1100: 597ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG); 598ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 599ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1550: 600ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG); 601ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 602ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss case ALCHEMY_CPU_AU1200: 603ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss au1200_usb_init(); 604ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss break; 605809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss case ALCHEMY_CPU_AU1300: 606809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss au1300_usb_init(); 607809f36c6f4a0568178c909ff1096ca83eae33f7dManuel Lauss break; 608ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss } 609ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 610ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss register_syscore_ops(&alchemy_usb_pm_ops); 611ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss 612ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss return 0; 613ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Lauss} 614ce6bc92285cabd0df1f154a9ef5aeb937b6de57eManuel Laussarch_initcall(alchemy_usb_init); 615