^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * USB block power/access management abstraction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Au1000+: The OHCI block control register is at the far end of the OHCI memory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * area. Au1550 has OHCI on different base address. No need to handle
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * UDC here.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Au1200: one register to control access and clocks to O/EHCI, UDC and OTG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * as well as the PHY for EHCI and UDC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/syscore_ops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/mach-au1x00/au1000.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /* control register offsets */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define AU1000_OHCICFG 0x7fffc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define AU1550_OHCICFG 0x07ffc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define AU1200_USBCFG 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* Au1000 USB block config bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define USBHEN_RD (1 << 4) /* OHCI reset-done indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define USBHEN_CE (1 << 3) /* OHCI block clock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define USBHEN_E (1 << 2) /* OHCI block enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define USBHEN_C (1 << 1) /* OHCI block coherency bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define USBHEN_BE (1 << 0) /* OHCI Big-Endian */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Au1200 USB config bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define USBCFG_PFEN (1 << 31) /* prefetch enable (undoc) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define USBCFG_RDCOMB (1 << 30) /* read combining (undoc) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define USBCFG_UNKNOWN (5 << 20) /* unknown, leave this way */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define USBCFG_SSD (1 << 23) /* serial short detect en */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) #define USBCFG_PPE (1 << 19) /* HS PHY PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define USBCFG_UCE (1 << 18) /* UDC clock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define USBCFG_ECE (1 << 17) /* EHCI clock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define USBCFG_OCE (1 << 16) /* OHCI clock enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define USBCFG_FLA(x) (((x) & 0x3f) << 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define USBCFG_UCAM (1 << 7) /* coherent access (undoc) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) #define USBCFG_GME (1 << 6) /* OTG mem access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define USBCFG_DBE (1 << 5) /* UDC busmaster enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define USBCFG_DME (1 << 4) /* UDC mem enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) #define USBCFG_EBE (1 << 3) /* EHCI busmaster enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define USBCFG_EME (1 << 2) /* EHCI mem enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define USBCFG_OBE (1 << 1) /* OHCI busmaster enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define USBCFG_OME (1 << 0) /* OHCI mem enable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define USBCFG_INIT_AU1200 (USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) USBCFG_GME | USBCFG_DBE | USBCFG_DME | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) USBCFG_OME)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* Au1300 USB config registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define USB_DWC_CTRL1 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) #define USB_DWC_CTRL2 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define USB_VBUS_TIMER 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define USB_SBUS_CTRL 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define USB_MSR_ERR 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define USB_DWC_CTRL3 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) #define USB_DWC_CTRL4 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define USB_OTG_STATUS 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define USB_DWC_CTRL5 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #define USB_DWC_CTRL6 0x30
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) #define USB_DWC_CTRL7 0x34
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define USB_PHY_STATUS 0xC0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define USB_INT_STATUS 0xC4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define USB_INT_ENABLE 0xC8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) #define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) #define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) #define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #define USB_DWC_CTRL3_OTG0_CKEN (1 << 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) #define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #define USB_INTEN_FORCE 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #define USB_INTEN_PHY 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define USB_INTEN_UDC 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define USB_INTEN_EHCI 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define USB_INTEN_OHCI1 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define USB_INTEN_OHCI0 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) static DEFINE_SPINLOCK(alchemy_usb_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned long r, s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) r = __raw_readl(base + USB_DWC_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) s = __raw_readl(base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* simply enable all PHYs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) USB_DWC_CTRL2_PHYRS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) __raw_writel(r, base + USB_DWC_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else if (!s) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /* no USB block active, do disable all PHYs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) USB_DWC_CTRL2_PHYRS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) __raw_writel(r, base + USB_DWC_CTRL2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) unsigned long r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) __raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) : USB_DWC_CTRL3_OHCI1_CKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) __raw_writel(r, base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) __au1300_usb_phyctl(base, enable); /* power up the PHYs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) r = __raw_readl(base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) __raw_writel(r, base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) /* reset the OHCI start clock bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) __raw_writel(0, base + USB_DWC_CTRL7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) r = __raw_readl(base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) __raw_writel(r, base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) r = __raw_readl(base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) : USB_DWC_CTRL3_OHCI1_CKEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) __raw_writel(r, base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static inline void __au1300_ehci_control(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned long r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) r = __raw_readl(base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) r |= USB_DWC_CTRL3_EHCI0_CKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) __raw_writel(r, base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) r = __raw_readl(base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) r |= USB_DWC_CTRL1_HSTRS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) __raw_writel(r, base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) r = __raw_readl(base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) r |= USB_INTEN_EHCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) __raw_writel(r, base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) r = __raw_readl(base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) r &= ~USB_INTEN_EHCI;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) __raw_writel(r, base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) r = __raw_readl(base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) r &= ~USB_DWC_CTRL1_HSTRS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) __raw_writel(r, base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) r = __raw_readl(base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) __raw_writel(r, base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static inline void __au1300_udc_control(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) unsigned long r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) r = __raw_readl(base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) r |= USB_DWC_CTRL1_DCRS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) __raw_writel(r, base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) r = __raw_readl(base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) r |= USB_INTEN_UDC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) __raw_writel(r, base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) r = __raw_readl(base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) r &= ~USB_INTEN_UDC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) __raw_writel(r, base + USB_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) r = __raw_readl(base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) r &= ~USB_DWC_CTRL1_DCRS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) __raw_writel(r, base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static inline void __au1300_otg_control(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) unsigned long r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) r = __raw_readl(base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) r |= USB_DWC_CTRL3_OTG0_CKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) __raw_writel(r, base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) r = __raw_readl(base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) r &= ~USB_DWC_CTRL1_OTGD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) __raw_writel(r, base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) r = __raw_readl(base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) r |= USB_DWC_CTRL1_OTGD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) __raw_writel(r, base + USB_DWC_CTRL1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) r = __raw_readl(base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) r &= ~USB_DWC_CTRL3_OTG0_CKEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) __raw_writel(r, base + USB_DWC_CTRL3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) __au1300_usb_phyctl(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static inline int au1300_usb_control(int block, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) void __iomem *base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) switch (block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) case ALCHEMY_USB_OHCI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) __au1300_ohci_control(base, enable, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) case ALCHEMY_USB_OHCI1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) __au1300_ohci_control(base, enable, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) case ALCHEMY_USB_EHCI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) __au1300_ehci_control(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) case ALCHEMY_USB_UDC0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) __au1300_udc_control(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case ALCHEMY_USB_OTG0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) __au1300_otg_control(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static inline void au1300_usb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) void __iomem *base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* set some sane defaults. Note: we don't fiddle with DWC_CTRL4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * here at all: Port 2 routing (EHCI or UDC) must be set either
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * by boot firmware or platform init code; I can't autodetect
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * a sane setting.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) __raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) __raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) __raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) __raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) /* set coherent access bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) __raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) static inline void __au1200_ohci_control(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) unsigned long r = __raw_readl(base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) __raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) udelay(2000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) __raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) static inline void __au1200_ehci_control(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) unsigned long r = __raw_readl(base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) __raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) if (!(r & USBCFG_UCE)) /* UDC also off? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) __raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) static inline void __au1200_udc_control(void __iomem *base, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) unsigned long r = __raw_readl(base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) __raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) if (!(r & USBCFG_ECE)) /* EHCI also off? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) r &= ~USBCFG_PPE; /* yes: disable HS PHY PLL */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) __raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) static inline int au1200_usb_control(int block, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) void __iomem *base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) switch (block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) case ALCHEMY_USB_OHCI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) __au1200_ohci_control(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) case ALCHEMY_USB_UDC0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) __au1200_udc_control(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) case ALCHEMY_USB_EHCI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) __au1200_ehci_control(base, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) /* initialize USB block(s) to a known working state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) static inline void au1200_usb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) void __iomem *base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) (void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) __raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) static inline int au1000_usb_init(unsigned long rb, int reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) unsigned long r = __raw_readl(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) struct clk *c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) /* 48MHz check. Don't init if no one can provide it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) c = clk_get(NULL, "usbh_clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) if (IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) if (clk_round_rate(c, 48000000) != 48000000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) clk_put(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (clk_set_rate(c, 48000000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) clk_put(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) clk_put(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #if defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) r |= USBHEN_BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) r |= USBHEN_C;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) __raw_writel(r, base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) static inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) unsigned long r = __raw_readl(base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) struct clk *c = clk_get(NULL, "usbh_clk");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) if (IS_ERR(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) if (clk_prepare_enable(c))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) __raw_writel(r | USBHEN_CE, base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) __raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) /* wait for reset complete (read reg twice: au1500 erratum) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) while (__raw_readl(base + creg),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) !(__raw_readl(base + creg) & USBHEN_RD))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) __raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) clk_disable_unprepare(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) clk_put(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) static inline int au1000_usb_control(int block, int enable, unsigned long rb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int creg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) switch (block) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) case ALCHEMY_USB_OHCI0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) __au1xx0_ohci_control(enable, rb, creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) * alchemy_usb_control - control Alchemy on-chip USB blocks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) * @block: USB block to target
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * @enable: set 1 to enable a block, 0 to disable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int alchemy_usb_control(int block, int enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) spin_lock_irqsave(&alchemy_usb_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) switch (alchemy_get_cputype()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) case ALCHEMY_CPU_AU1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) case ALCHEMY_CPU_AU1500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) case ALCHEMY_CPU_AU1100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) ret = au1000_usb_control(block, enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) case ALCHEMY_CPU_AU1550:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) ret = au1000_usb_control(block, enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) case ALCHEMY_CPU_AU1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) ret = au1200_usb_control(block, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) case ALCHEMY_CPU_AU1300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) ret = au1300_usb_control(block, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) spin_unlock_irqrestore(&alchemy_usb_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) EXPORT_SYMBOL_GPL(alchemy_usb_control);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) static unsigned long alchemy_usb_pmdata[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) static void au1000_usb_pm(unsigned long br, int creg, int susp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) void __iomem *base = (void __iomem *)KSEG1ADDR(br);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (susp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) alchemy_usb_pmdata[0] = __raw_readl(base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) /* There appears to be some undocumented reset register.... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) __raw_writel(0, base + 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) __raw_writel(0, base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) __raw_writel(alchemy_usb_pmdata[0], base + creg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) static void au1200_usb_pm(int susp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) void __iomem *base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) (void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) if (susp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) /* save OTG_CAP/MUX registers which indicate port routing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) /* FIXME: write an OTG driver to do that */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) /* restore access to all MMIO areas */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) au1200_usb_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /* restore OTG_CAP/MUX registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) __raw_writel(alchemy_usb_pmdata[0], base + 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) __raw_writel(alchemy_usb_pmdata[1], base + 0x04);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) static void au1300_usb_pm(int susp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) void __iomem *base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) (void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) /* remember Port2 routing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) if (susp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) au1300_usb_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) __raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static void alchemy_usb_pm(int susp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) switch (alchemy_get_cputype()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case ALCHEMY_CPU_AU1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) case ALCHEMY_CPU_AU1500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) case ALCHEMY_CPU_AU1100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) case ALCHEMY_CPU_AU1550:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) case ALCHEMY_CPU_AU1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) au1200_usb_pm(susp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) case ALCHEMY_CPU_AU1300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) au1300_usb_pm(susp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) static int alchemy_usb_suspend(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) alchemy_usb_pm(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) static void alchemy_usb_resume(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) alchemy_usb_pm(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) static struct syscore_ops alchemy_usb_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) .suspend = alchemy_usb_suspend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) .resume = alchemy_usb_resume,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static int __init alchemy_usb_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) switch (alchemy_get_cputype()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) case ALCHEMY_CPU_AU1000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) case ALCHEMY_CPU_AU1500:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) case ALCHEMY_CPU_AU1100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) AU1000_OHCICFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) case ALCHEMY_CPU_AU1550:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) AU1550_OHCICFG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) case ALCHEMY_CPU_AU1200:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) au1200_usb_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) case ALCHEMY_CPU_AU1300:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) au1300_usb_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) register_syscore_ops(&alchemy_usb_pm_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) arch_initcall(alchemy_usb_init);