18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * USB block power/access management abstraction.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Au1000+: The OHCI block control register is at the far end of the OHCI memory
68c2ecf20Sopenharmony_ci *	    area. Au1550 has OHCI on different base address. No need to handle
78c2ecf20Sopenharmony_ci *	    UDC here.
88c2ecf20Sopenharmony_ci * Au1200:  one register to control access and clocks to O/EHCI, UDC and OTG
98c2ecf20Sopenharmony_ci *	    as well as the PHY for EHCI and UDC.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/clk.h>
148c2ecf20Sopenharmony_ci#include <linux/export.h>
158c2ecf20Sopenharmony_ci#include <linux/init.h>
168c2ecf20Sopenharmony_ci#include <linux/io.h>
178c2ecf20Sopenharmony_ci#include <linux/spinlock.h>
188c2ecf20Sopenharmony_ci#include <linux/syscore_ops.h>
198c2ecf20Sopenharmony_ci#include <asm/cpu.h>
208c2ecf20Sopenharmony_ci#include <asm/mach-au1x00/au1000.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* control register offsets */
238c2ecf20Sopenharmony_ci#define AU1000_OHCICFG	0x7fffc
248c2ecf20Sopenharmony_ci#define AU1550_OHCICFG	0x07ffc
258c2ecf20Sopenharmony_ci#define AU1200_USBCFG	0x04
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ci/* Au1000 USB block config bits */
288c2ecf20Sopenharmony_ci#define USBHEN_RD	(1 << 4)		/* OHCI reset-done indicator */
298c2ecf20Sopenharmony_ci#define USBHEN_CE	(1 << 3)		/* OHCI block clock enable */
308c2ecf20Sopenharmony_ci#define USBHEN_E	(1 << 2)		/* OHCI block enable */
318c2ecf20Sopenharmony_ci#define USBHEN_C	(1 << 1)		/* OHCI block coherency bit */
328c2ecf20Sopenharmony_ci#define USBHEN_BE	(1 << 0)		/* OHCI Big-Endian */
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* Au1200 USB config bits */
358c2ecf20Sopenharmony_ci#define USBCFG_PFEN	(1 << 31)		/* prefetch enable (undoc) */
368c2ecf20Sopenharmony_ci#define USBCFG_RDCOMB	(1 << 30)		/* read combining (undoc) */
378c2ecf20Sopenharmony_ci#define USBCFG_UNKNOWN	(5 << 20)		/* unknown, leave this way */
388c2ecf20Sopenharmony_ci#define USBCFG_SSD	(1 << 23)		/* serial short detect en */
398c2ecf20Sopenharmony_ci#define USBCFG_PPE	(1 << 19)		/* HS PHY PLL */
408c2ecf20Sopenharmony_ci#define USBCFG_UCE	(1 << 18)		/* UDC clock enable */
418c2ecf20Sopenharmony_ci#define USBCFG_ECE	(1 << 17)		/* EHCI clock enable */
428c2ecf20Sopenharmony_ci#define USBCFG_OCE	(1 << 16)		/* OHCI clock enable */
438c2ecf20Sopenharmony_ci#define USBCFG_FLA(x)	(((x) & 0x3f) << 8)
448c2ecf20Sopenharmony_ci#define USBCFG_UCAM	(1 << 7)		/* coherent access (undoc) */
458c2ecf20Sopenharmony_ci#define USBCFG_GME	(1 << 6)		/* OTG mem access */
468c2ecf20Sopenharmony_ci#define USBCFG_DBE	(1 << 5)		/* UDC busmaster enable */
478c2ecf20Sopenharmony_ci#define USBCFG_DME	(1 << 4)		/* UDC mem enable */
488c2ecf20Sopenharmony_ci#define USBCFG_EBE	(1 << 3)		/* EHCI busmaster enable */
498c2ecf20Sopenharmony_ci#define USBCFG_EME	(1 << 2)		/* EHCI mem enable */
508c2ecf20Sopenharmony_ci#define USBCFG_OBE	(1 << 1)		/* OHCI busmaster enable */
518c2ecf20Sopenharmony_ci#define USBCFG_OME	(1 << 0)		/* OHCI mem enable */
528c2ecf20Sopenharmony_ci#define USBCFG_INIT_AU1200	(USBCFG_PFEN | USBCFG_RDCOMB | USBCFG_UNKNOWN |\
538c2ecf20Sopenharmony_ci				 USBCFG_SSD | USBCFG_FLA(0x20) | USBCFG_UCAM | \
548c2ecf20Sopenharmony_ci				 USBCFG_GME | USBCFG_DBE | USBCFG_DME |	       \
558c2ecf20Sopenharmony_ci				 USBCFG_EBE | USBCFG_EME | USBCFG_OBE |	       \
568c2ecf20Sopenharmony_ci				 USBCFG_OME)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* Au1300 USB config registers */
598c2ecf20Sopenharmony_ci#define USB_DWC_CTRL1		0x00
608c2ecf20Sopenharmony_ci#define USB_DWC_CTRL2		0x04
618c2ecf20Sopenharmony_ci#define USB_VBUS_TIMER		0x10
628c2ecf20Sopenharmony_ci#define USB_SBUS_CTRL		0x14
638c2ecf20Sopenharmony_ci#define USB_MSR_ERR		0x18
648c2ecf20Sopenharmony_ci#define USB_DWC_CTRL3		0x1C
658c2ecf20Sopenharmony_ci#define USB_DWC_CTRL4		0x20
668c2ecf20Sopenharmony_ci#define USB_OTG_STATUS		0x28
678c2ecf20Sopenharmony_ci#define USB_DWC_CTRL5		0x2C
688c2ecf20Sopenharmony_ci#define USB_DWC_CTRL6		0x30
698c2ecf20Sopenharmony_ci#define USB_DWC_CTRL7		0x34
708c2ecf20Sopenharmony_ci#define USB_PHY_STATUS		0xC0
718c2ecf20Sopenharmony_ci#define USB_INT_STATUS		0xC4
728c2ecf20Sopenharmony_ci#define USB_INT_ENABLE		0xC8
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#define USB_DWC_CTRL1_OTGD	0x04 /* set to DISable OTG */
758c2ecf20Sopenharmony_ci#define USB_DWC_CTRL1_HSTRS	0x02 /* set to ENable EHCI */
768c2ecf20Sopenharmony_ci#define USB_DWC_CTRL1_DCRS	0x01 /* set to ENable UDC */
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#define USB_DWC_CTRL2_PHY1RS	0x04 /* set to enable PHY1 */
798c2ecf20Sopenharmony_ci#define USB_DWC_CTRL2_PHY0RS	0x02 /* set to enable PHY0 */
808c2ecf20Sopenharmony_ci#define USB_DWC_CTRL2_PHYRS	0x01 /* set to enable PHY */
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ci#define USB_DWC_CTRL3_OHCI1_CKEN	(1 << 19)
838c2ecf20Sopenharmony_ci#define USB_DWC_CTRL3_OHCI0_CKEN	(1 << 18)
848c2ecf20Sopenharmony_ci#define USB_DWC_CTRL3_EHCI0_CKEN	(1 << 17)
858c2ecf20Sopenharmony_ci#define USB_DWC_CTRL3_OTG0_CKEN		(1 << 16)
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define USB_SBUS_CTRL_SBCA		0x04 /* coherent access */
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci#define USB_INTEN_FORCE			0x20
908c2ecf20Sopenharmony_ci#define USB_INTEN_PHY			0x10
918c2ecf20Sopenharmony_ci#define USB_INTEN_UDC			0x08
928c2ecf20Sopenharmony_ci#define USB_INTEN_EHCI			0x04
938c2ecf20Sopenharmony_ci#define USB_INTEN_OHCI1			0x02
948c2ecf20Sopenharmony_ci#define USB_INTEN_OHCI0			0x01
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(alchemy_usb_lock);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic inline void __au1300_usb_phyctl(void __iomem *base, int enable)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	unsigned long r, s;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	r = __raw_readl(base + USB_DWC_CTRL2);
1038c2ecf20Sopenharmony_ci	s = __raw_readl(base + USB_DWC_CTRL3);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci	s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
1068c2ecf20Sopenharmony_ci		USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci	if (enable) {
1098c2ecf20Sopenharmony_ci		/* simply enable all PHYs */
1108c2ecf20Sopenharmony_ci		r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
1118c2ecf20Sopenharmony_ci		     USB_DWC_CTRL2_PHYRS;
1128c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL2);
1138c2ecf20Sopenharmony_ci		wmb();
1148c2ecf20Sopenharmony_ci	} else if (!s) {
1158c2ecf20Sopenharmony_ci		/* no USB block active, do disable all PHYs */
1168c2ecf20Sopenharmony_ci		r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
1178c2ecf20Sopenharmony_ci		       USB_DWC_CTRL2_PHYRS);
1188c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL2);
1198c2ecf20Sopenharmony_ci		wmb();
1208c2ecf20Sopenharmony_ci	}
1218c2ecf20Sopenharmony_ci}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_cistatic inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
1248c2ecf20Sopenharmony_ci{
1258c2ecf20Sopenharmony_ci	unsigned long r;
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	if (enable) {
1288c2ecf20Sopenharmony_ci		__raw_writel(1, base + USB_DWC_CTRL7);	/* start OHCI clock */
1298c2ecf20Sopenharmony_ci		wmb();
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL3);	/* enable OHCI block */
1328c2ecf20Sopenharmony_ci		r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
1338c2ecf20Sopenharmony_ci			       : USB_DWC_CTRL3_OHCI1_CKEN;
1348c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL3);
1358c2ecf20Sopenharmony_ci		wmb();
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);	/* power up the PHYs */
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_INT_ENABLE);
1408c2ecf20Sopenharmony_ci		r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
1418c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_INT_ENABLE);
1428c2ecf20Sopenharmony_ci		wmb();
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci		/* reset the OHCI start clock bit */
1458c2ecf20Sopenharmony_ci		__raw_writel(0, base + USB_DWC_CTRL7);
1468c2ecf20Sopenharmony_ci		wmb();
1478c2ecf20Sopenharmony_ci	} else {
1488c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_INT_ENABLE);
1498c2ecf20Sopenharmony_ci		r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
1508c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_INT_ENABLE);
1518c2ecf20Sopenharmony_ci		wmb();
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL3);
1548c2ecf20Sopenharmony_ci		r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
1558c2ecf20Sopenharmony_ci				 : USB_DWC_CTRL3_OHCI1_CKEN);
1568c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL3);
1578c2ecf20Sopenharmony_ci		wmb();
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
1608c2ecf20Sopenharmony_ci	}
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic inline void __au1300_ehci_control(void __iomem *base, int enable)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	unsigned long r;
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci	if (enable) {
1688c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL3);
1698c2ecf20Sopenharmony_ci		r |= USB_DWC_CTRL3_EHCI0_CKEN;
1708c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL3);
1718c2ecf20Sopenharmony_ci		wmb();
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL1);
1748c2ecf20Sopenharmony_ci		r |= USB_DWC_CTRL1_HSTRS;
1758c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL1);
1768c2ecf20Sopenharmony_ci		wmb();
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_INT_ENABLE);
1818c2ecf20Sopenharmony_ci		r |= USB_INTEN_EHCI;
1828c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_INT_ENABLE);
1838c2ecf20Sopenharmony_ci		wmb();
1848c2ecf20Sopenharmony_ci	} else {
1858c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_INT_ENABLE);
1868c2ecf20Sopenharmony_ci		r &= ~USB_INTEN_EHCI;
1878c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_INT_ENABLE);
1888c2ecf20Sopenharmony_ci		wmb();
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL1);
1918c2ecf20Sopenharmony_ci		r &= ~USB_DWC_CTRL1_HSTRS;
1928c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL1);
1938c2ecf20Sopenharmony_ci		wmb();
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL3);
1968c2ecf20Sopenharmony_ci		r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
1978c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL3);
1988c2ecf20Sopenharmony_ci		wmb();
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic inline void __au1300_udc_control(void __iomem *base, int enable)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	unsigned long r;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	if (enable) {
2098c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL1);
2108c2ecf20Sopenharmony_ci		r |= USB_DWC_CTRL1_DCRS;
2118c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL1);
2128c2ecf20Sopenharmony_ci		wmb();
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_INT_ENABLE);
2178c2ecf20Sopenharmony_ci		r |= USB_INTEN_UDC;
2188c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_INT_ENABLE);
2198c2ecf20Sopenharmony_ci		wmb();
2208c2ecf20Sopenharmony_ci	} else {
2218c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_INT_ENABLE);
2228c2ecf20Sopenharmony_ci		r &= ~USB_INTEN_UDC;
2238c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_INT_ENABLE);
2248c2ecf20Sopenharmony_ci		wmb();
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL1);
2278c2ecf20Sopenharmony_ci		r &= ~USB_DWC_CTRL1_DCRS;
2288c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL1);
2298c2ecf20Sopenharmony_ci		wmb();
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
2328c2ecf20Sopenharmony_ci	}
2338c2ecf20Sopenharmony_ci}
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_cistatic inline void __au1300_otg_control(void __iomem *base, int enable)
2368c2ecf20Sopenharmony_ci{
2378c2ecf20Sopenharmony_ci	unsigned long r;
2388c2ecf20Sopenharmony_ci	if (enable) {
2398c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL3);
2408c2ecf20Sopenharmony_ci		r |= USB_DWC_CTRL3_OTG0_CKEN;
2418c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL3);
2428c2ecf20Sopenharmony_ci		wmb();
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL1);
2458c2ecf20Sopenharmony_ci		r &= ~USB_DWC_CTRL1_OTGD;
2468c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL1);
2478c2ecf20Sopenharmony_ci		wmb();
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
2508c2ecf20Sopenharmony_ci	} else {
2518c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL1);
2528c2ecf20Sopenharmony_ci		r |= USB_DWC_CTRL1_OTGD;
2538c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL1);
2548c2ecf20Sopenharmony_ci		wmb();
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci		r = __raw_readl(base + USB_DWC_CTRL3);
2578c2ecf20Sopenharmony_ci		r &= ~USB_DWC_CTRL3_OTG0_CKEN;
2588c2ecf20Sopenharmony_ci		__raw_writel(r, base + USB_DWC_CTRL3);
2598c2ecf20Sopenharmony_ci		wmb();
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci		__au1300_usb_phyctl(base, enable);
2628c2ecf20Sopenharmony_ci	}
2638c2ecf20Sopenharmony_ci}
2648c2ecf20Sopenharmony_ci
2658c2ecf20Sopenharmony_cistatic inline int au1300_usb_control(int block, int enable)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	void __iomem *base =
2688c2ecf20Sopenharmony_ci		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
2698c2ecf20Sopenharmony_ci	int ret = 0;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	switch (block) {
2728c2ecf20Sopenharmony_ci	case ALCHEMY_USB_OHCI0:
2738c2ecf20Sopenharmony_ci		__au1300_ohci_control(base, enable, 0);
2748c2ecf20Sopenharmony_ci		break;
2758c2ecf20Sopenharmony_ci	case ALCHEMY_USB_OHCI1:
2768c2ecf20Sopenharmony_ci		__au1300_ohci_control(base, enable, 1);
2778c2ecf20Sopenharmony_ci		break;
2788c2ecf20Sopenharmony_ci	case ALCHEMY_USB_EHCI0:
2798c2ecf20Sopenharmony_ci		__au1300_ehci_control(base, enable);
2808c2ecf20Sopenharmony_ci		break;
2818c2ecf20Sopenharmony_ci	case ALCHEMY_USB_UDC0:
2828c2ecf20Sopenharmony_ci		__au1300_udc_control(base, enable);
2838c2ecf20Sopenharmony_ci		break;
2848c2ecf20Sopenharmony_ci	case ALCHEMY_USB_OTG0:
2858c2ecf20Sopenharmony_ci		__au1300_otg_control(base, enable);
2868c2ecf20Sopenharmony_ci		break;
2878c2ecf20Sopenharmony_ci	default:
2888c2ecf20Sopenharmony_ci		ret = -ENODEV;
2898c2ecf20Sopenharmony_ci	}
2908c2ecf20Sopenharmony_ci	return ret;
2918c2ecf20Sopenharmony_ci}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_cistatic inline void au1300_usb_init(void)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	void __iomem *base =
2968c2ecf20Sopenharmony_ci		(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	/* set some sane defaults.  Note: we don't fiddle with DWC_CTRL4
2998c2ecf20Sopenharmony_ci	 * here at all: Port 2 routing (EHCI or UDC) must be set either
3008c2ecf20Sopenharmony_ci	 * by boot firmware or platform init code; I can't autodetect
3018c2ecf20Sopenharmony_ci	 * a sane setting.
3028c2ecf20Sopenharmony_ci	 */
3038c2ecf20Sopenharmony_ci	__raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
3048c2ecf20Sopenharmony_ci	wmb();
3058c2ecf20Sopenharmony_ci	__raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
3068c2ecf20Sopenharmony_ci	wmb();
3078c2ecf20Sopenharmony_ci	__raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
3088c2ecf20Sopenharmony_ci	wmb();
3098c2ecf20Sopenharmony_ci	__raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
3108c2ecf20Sopenharmony_ci	wmb();
3118c2ecf20Sopenharmony_ci	/* set coherent access bit */
3128c2ecf20Sopenharmony_ci	__raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
3138c2ecf20Sopenharmony_ci	wmb();
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_cistatic inline void __au1200_ohci_control(void __iomem *base, int enable)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci	unsigned long r = __raw_readl(base + AU1200_USBCFG);
3198c2ecf20Sopenharmony_ci	if (enable) {
3208c2ecf20Sopenharmony_ci		__raw_writel(r | USBCFG_OCE, base + AU1200_USBCFG);
3218c2ecf20Sopenharmony_ci		wmb();
3228c2ecf20Sopenharmony_ci		udelay(2000);
3238c2ecf20Sopenharmony_ci	} else {
3248c2ecf20Sopenharmony_ci		__raw_writel(r & ~USBCFG_OCE, base + AU1200_USBCFG);
3258c2ecf20Sopenharmony_ci		wmb();
3268c2ecf20Sopenharmony_ci		udelay(1000);
3278c2ecf20Sopenharmony_ci	}
3288c2ecf20Sopenharmony_ci}
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_cistatic inline void __au1200_ehci_control(void __iomem *base, int enable)
3318c2ecf20Sopenharmony_ci{
3328c2ecf20Sopenharmony_ci	unsigned long r = __raw_readl(base + AU1200_USBCFG);
3338c2ecf20Sopenharmony_ci	if (enable) {
3348c2ecf20Sopenharmony_ci		__raw_writel(r | USBCFG_ECE | USBCFG_PPE, base + AU1200_USBCFG);
3358c2ecf20Sopenharmony_ci		wmb();
3368c2ecf20Sopenharmony_ci		udelay(1000);
3378c2ecf20Sopenharmony_ci	} else {
3388c2ecf20Sopenharmony_ci		if (!(r & USBCFG_UCE))		/* UDC also off? */
3398c2ecf20Sopenharmony_ci			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
3408c2ecf20Sopenharmony_ci		__raw_writel(r & ~USBCFG_ECE, base + AU1200_USBCFG);
3418c2ecf20Sopenharmony_ci		wmb();
3428c2ecf20Sopenharmony_ci		udelay(1000);
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_cistatic inline void __au1200_udc_control(void __iomem *base, int enable)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	unsigned long r = __raw_readl(base + AU1200_USBCFG);
3498c2ecf20Sopenharmony_ci	if (enable) {
3508c2ecf20Sopenharmony_ci		__raw_writel(r | USBCFG_UCE | USBCFG_PPE, base + AU1200_USBCFG);
3518c2ecf20Sopenharmony_ci		wmb();
3528c2ecf20Sopenharmony_ci	} else {
3538c2ecf20Sopenharmony_ci		if (!(r & USBCFG_ECE))		/* EHCI also off? */
3548c2ecf20Sopenharmony_ci			r &= ~USBCFG_PPE;	/* yes: disable HS PHY PLL */
3558c2ecf20Sopenharmony_ci		__raw_writel(r & ~USBCFG_UCE, base + AU1200_USBCFG);
3568c2ecf20Sopenharmony_ci		wmb();
3578c2ecf20Sopenharmony_ci	}
3588c2ecf20Sopenharmony_ci}
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic inline int au1200_usb_control(int block, int enable)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	void __iomem *base =
3638c2ecf20Sopenharmony_ci			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci	switch (block) {
3668c2ecf20Sopenharmony_ci	case ALCHEMY_USB_OHCI0:
3678c2ecf20Sopenharmony_ci		__au1200_ohci_control(base, enable);
3688c2ecf20Sopenharmony_ci		break;
3698c2ecf20Sopenharmony_ci	case ALCHEMY_USB_UDC0:
3708c2ecf20Sopenharmony_ci		__au1200_udc_control(base, enable);
3718c2ecf20Sopenharmony_ci		break;
3728c2ecf20Sopenharmony_ci	case ALCHEMY_USB_EHCI0:
3738c2ecf20Sopenharmony_ci		__au1200_ehci_control(base, enable);
3748c2ecf20Sopenharmony_ci		break;
3758c2ecf20Sopenharmony_ci	default:
3768c2ecf20Sopenharmony_ci		return -ENODEV;
3778c2ecf20Sopenharmony_ci	}
3788c2ecf20Sopenharmony_ci	return 0;
3798c2ecf20Sopenharmony_ci}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci/* initialize USB block(s) to a known working state */
3838c2ecf20Sopenharmony_cistatic inline void au1200_usb_init(void)
3848c2ecf20Sopenharmony_ci{
3858c2ecf20Sopenharmony_ci	void __iomem *base =
3868c2ecf20Sopenharmony_ci			(void __iomem *)KSEG1ADDR(AU1200_USB_CTL_PHYS_ADDR);
3878c2ecf20Sopenharmony_ci	__raw_writel(USBCFG_INIT_AU1200, base + AU1200_USBCFG);
3888c2ecf20Sopenharmony_ci	wmb();
3898c2ecf20Sopenharmony_ci	udelay(1000);
3908c2ecf20Sopenharmony_ci}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cistatic inline int au1000_usb_init(unsigned long rb, int reg)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	void __iomem *base = (void __iomem *)KSEG1ADDR(rb + reg);
3958c2ecf20Sopenharmony_ci	unsigned long r = __raw_readl(base);
3968c2ecf20Sopenharmony_ci	struct clk *c;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci	/* 48MHz check. Don't init if no one can provide it */
3998c2ecf20Sopenharmony_ci	c = clk_get(NULL, "usbh_clk");
4008c2ecf20Sopenharmony_ci	if (IS_ERR(c))
4018c2ecf20Sopenharmony_ci		return -ENODEV;
4028c2ecf20Sopenharmony_ci	if (clk_round_rate(c, 48000000) != 48000000) {
4038c2ecf20Sopenharmony_ci		clk_put(c);
4048c2ecf20Sopenharmony_ci		return -ENODEV;
4058c2ecf20Sopenharmony_ci	}
4068c2ecf20Sopenharmony_ci	if (clk_set_rate(c, 48000000)) {
4078c2ecf20Sopenharmony_ci		clk_put(c);
4088c2ecf20Sopenharmony_ci		return -ENODEV;
4098c2ecf20Sopenharmony_ci	}
4108c2ecf20Sopenharmony_ci	clk_put(c);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci#if defined(__BIG_ENDIAN)
4138c2ecf20Sopenharmony_ci	r |= USBHEN_BE;
4148c2ecf20Sopenharmony_ci#endif
4158c2ecf20Sopenharmony_ci	r |= USBHEN_C;
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	__raw_writel(r, base);
4188c2ecf20Sopenharmony_ci	wmb();
4198c2ecf20Sopenharmony_ci	udelay(1000);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	return 0;
4228c2ecf20Sopenharmony_ci}
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_cistatic inline void __au1xx0_ohci_control(int enable, unsigned long rb, int creg)
4268c2ecf20Sopenharmony_ci{
4278c2ecf20Sopenharmony_ci	void __iomem *base = (void __iomem *)KSEG1ADDR(rb);
4288c2ecf20Sopenharmony_ci	unsigned long r = __raw_readl(base + creg);
4298c2ecf20Sopenharmony_ci	struct clk *c = clk_get(NULL, "usbh_clk");
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	if (IS_ERR(c))
4328c2ecf20Sopenharmony_ci		return;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	if (enable) {
4358c2ecf20Sopenharmony_ci		if (clk_prepare_enable(c))
4368c2ecf20Sopenharmony_ci			goto out;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci		__raw_writel(r | USBHEN_CE, base + creg);
4398c2ecf20Sopenharmony_ci		wmb();
4408c2ecf20Sopenharmony_ci		udelay(1000);
4418c2ecf20Sopenharmony_ci		__raw_writel(r | USBHEN_CE | USBHEN_E, base + creg);
4428c2ecf20Sopenharmony_ci		wmb();
4438c2ecf20Sopenharmony_ci		udelay(1000);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci		/* wait for reset complete (read reg twice: au1500 erratum) */
4468c2ecf20Sopenharmony_ci		while (__raw_readl(base + creg),
4478c2ecf20Sopenharmony_ci			!(__raw_readl(base + creg) & USBHEN_RD))
4488c2ecf20Sopenharmony_ci			udelay(1000);
4498c2ecf20Sopenharmony_ci	} else {
4508c2ecf20Sopenharmony_ci		__raw_writel(r & ~(USBHEN_CE | USBHEN_E), base + creg);
4518c2ecf20Sopenharmony_ci		wmb();
4528c2ecf20Sopenharmony_ci		clk_disable_unprepare(c);
4538c2ecf20Sopenharmony_ci	}
4548c2ecf20Sopenharmony_ciout:
4558c2ecf20Sopenharmony_ci	clk_put(c);
4568c2ecf20Sopenharmony_ci}
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic inline int au1000_usb_control(int block, int enable, unsigned long rb,
4598c2ecf20Sopenharmony_ci				     int creg)
4608c2ecf20Sopenharmony_ci{
4618c2ecf20Sopenharmony_ci	int ret = 0;
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ci	switch (block) {
4648c2ecf20Sopenharmony_ci	case ALCHEMY_USB_OHCI0:
4658c2ecf20Sopenharmony_ci		__au1xx0_ohci_control(enable, rb, creg);
4668c2ecf20Sopenharmony_ci		break;
4678c2ecf20Sopenharmony_ci	default:
4688c2ecf20Sopenharmony_ci		ret = -ENODEV;
4698c2ecf20Sopenharmony_ci	}
4708c2ecf20Sopenharmony_ci	return ret;
4718c2ecf20Sopenharmony_ci}
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci/*
4748c2ecf20Sopenharmony_ci * alchemy_usb_control - control Alchemy on-chip USB blocks
4758c2ecf20Sopenharmony_ci * @block:	USB block to target
4768c2ecf20Sopenharmony_ci * @enable:	set 1 to enable a block, 0 to disable
4778c2ecf20Sopenharmony_ci */
4788c2ecf20Sopenharmony_ciint alchemy_usb_control(int block, int enable)
4798c2ecf20Sopenharmony_ci{
4808c2ecf20Sopenharmony_ci	unsigned long flags;
4818c2ecf20Sopenharmony_ci	int ret;
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	spin_lock_irqsave(&alchemy_usb_lock, flags);
4848c2ecf20Sopenharmony_ci	switch (alchemy_get_cputype()) {
4858c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1000:
4868c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1500:
4878c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1100:
4888c2ecf20Sopenharmony_ci		ret = au1000_usb_control(block, enable,
4898c2ecf20Sopenharmony_ci			AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG);
4908c2ecf20Sopenharmony_ci		break;
4918c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1550:
4928c2ecf20Sopenharmony_ci		ret = au1000_usb_control(block, enable,
4938c2ecf20Sopenharmony_ci			AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG);
4948c2ecf20Sopenharmony_ci		break;
4958c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1200:
4968c2ecf20Sopenharmony_ci		ret = au1200_usb_control(block, enable);
4978c2ecf20Sopenharmony_ci		break;
4988c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1300:
4998c2ecf20Sopenharmony_ci		ret = au1300_usb_control(block, enable);
5008c2ecf20Sopenharmony_ci		break;
5018c2ecf20Sopenharmony_ci	default:
5028c2ecf20Sopenharmony_ci		ret = -ENODEV;
5038c2ecf20Sopenharmony_ci	}
5048c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&alchemy_usb_lock, flags);
5058c2ecf20Sopenharmony_ci	return ret;
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(alchemy_usb_control);
5088c2ecf20Sopenharmony_ci
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_cistatic unsigned long alchemy_usb_pmdata[2];
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic void au1000_usb_pm(unsigned long br, int creg, int susp)
5138c2ecf20Sopenharmony_ci{
5148c2ecf20Sopenharmony_ci	void __iomem *base = (void __iomem *)KSEG1ADDR(br);
5158c2ecf20Sopenharmony_ci
5168c2ecf20Sopenharmony_ci	if (susp) {
5178c2ecf20Sopenharmony_ci		alchemy_usb_pmdata[0] = __raw_readl(base + creg);
5188c2ecf20Sopenharmony_ci		/* There appears to be some undocumented reset register.... */
5198c2ecf20Sopenharmony_ci		__raw_writel(0, base + 0x04);
5208c2ecf20Sopenharmony_ci		wmb();
5218c2ecf20Sopenharmony_ci		__raw_writel(0, base + creg);
5228c2ecf20Sopenharmony_ci		wmb();
5238c2ecf20Sopenharmony_ci	} else {
5248c2ecf20Sopenharmony_ci		__raw_writel(alchemy_usb_pmdata[0], base + creg);
5258c2ecf20Sopenharmony_ci		wmb();
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci}
5288c2ecf20Sopenharmony_ci
5298c2ecf20Sopenharmony_cistatic void au1200_usb_pm(int susp)
5308c2ecf20Sopenharmony_ci{
5318c2ecf20Sopenharmony_ci	void __iomem *base =
5328c2ecf20Sopenharmony_ci			(void __iomem *)KSEG1ADDR(AU1200_USB_OTG_PHYS_ADDR);
5338c2ecf20Sopenharmony_ci	if (susp) {
5348c2ecf20Sopenharmony_ci		/* save OTG_CAP/MUX registers which indicate port routing */
5358c2ecf20Sopenharmony_ci		/* FIXME: write an OTG driver to do that */
5368c2ecf20Sopenharmony_ci		alchemy_usb_pmdata[0] = __raw_readl(base + 0x00);
5378c2ecf20Sopenharmony_ci		alchemy_usb_pmdata[1] = __raw_readl(base + 0x04);
5388c2ecf20Sopenharmony_ci	} else {
5398c2ecf20Sopenharmony_ci		/* restore access to all MMIO areas */
5408c2ecf20Sopenharmony_ci		au1200_usb_init();
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_ci		/* restore OTG_CAP/MUX registers */
5438c2ecf20Sopenharmony_ci		__raw_writel(alchemy_usb_pmdata[0], base + 0x00);
5448c2ecf20Sopenharmony_ci		__raw_writel(alchemy_usb_pmdata[1], base + 0x04);
5458c2ecf20Sopenharmony_ci		wmb();
5468c2ecf20Sopenharmony_ci	}
5478c2ecf20Sopenharmony_ci}
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_cistatic void au1300_usb_pm(int susp)
5508c2ecf20Sopenharmony_ci{
5518c2ecf20Sopenharmony_ci	void __iomem *base =
5528c2ecf20Sopenharmony_ci			(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
5538c2ecf20Sopenharmony_ci	/* remember Port2 routing */
5548c2ecf20Sopenharmony_ci	if (susp) {
5558c2ecf20Sopenharmony_ci		alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
5568c2ecf20Sopenharmony_ci	} else {
5578c2ecf20Sopenharmony_ci		au1300_usb_init();
5588c2ecf20Sopenharmony_ci		__raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
5598c2ecf20Sopenharmony_ci		wmb();
5608c2ecf20Sopenharmony_ci	}
5618c2ecf20Sopenharmony_ci}
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_cistatic void alchemy_usb_pm(int susp)
5648c2ecf20Sopenharmony_ci{
5658c2ecf20Sopenharmony_ci	switch (alchemy_get_cputype()) {
5668c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1000:
5678c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1500:
5688c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1100:
5698c2ecf20Sopenharmony_ci		au1000_usb_pm(AU1000_USB_OHCI_PHYS_ADDR, AU1000_OHCICFG, susp);
5708c2ecf20Sopenharmony_ci		break;
5718c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1550:
5728c2ecf20Sopenharmony_ci		au1000_usb_pm(AU1550_USB_OHCI_PHYS_ADDR, AU1550_OHCICFG, susp);
5738c2ecf20Sopenharmony_ci		break;
5748c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1200:
5758c2ecf20Sopenharmony_ci		au1200_usb_pm(susp);
5768c2ecf20Sopenharmony_ci		break;
5778c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1300:
5788c2ecf20Sopenharmony_ci		au1300_usb_pm(susp);
5798c2ecf20Sopenharmony_ci		break;
5808c2ecf20Sopenharmony_ci	}
5818c2ecf20Sopenharmony_ci}
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cistatic int alchemy_usb_suspend(void)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	alchemy_usb_pm(1);
5868c2ecf20Sopenharmony_ci	return 0;
5878c2ecf20Sopenharmony_ci}
5888c2ecf20Sopenharmony_ci
5898c2ecf20Sopenharmony_cistatic void alchemy_usb_resume(void)
5908c2ecf20Sopenharmony_ci{
5918c2ecf20Sopenharmony_ci	alchemy_usb_pm(0);
5928c2ecf20Sopenharmony_ci}
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_cistatic struct syscore_ops alchemy_usb_pm_ops = {
5958c2ecf20Sopenharmony_ci	.suspend	= alchemy_usb_suspend,
5968c2ecf20Sopenharmony_ci	.resume		= alchemy_usb_resume,
5978c2ecf20Sopenharmony_ci};
5988c2ecf20Sopenharmony_ci
5998c2ecf20Sopenharmony_cistatic int __init alchemy_usb_init(void)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	int ret = 0;
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	switch (alchemy_get_cputype()) {
6048c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1000:
6058c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1500:
6068c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1100:
6078c2ecf20Sopenharmony_ci		ret = au1000_usb_init(AU1000_USB_OHCI_PHYS_ADDR,
6088c2ecf20Sopenharmony_ci				      AU1000_OHCICFG);
6098c2ecf20Sopenharmony_ci		break;
6108c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1550:
6118c2ecf20Sopenharmony_ci		ret = au1000_usb_init(AU1550_USB_OHCI_PHYS_ADDR,
6128c2ecf20Sopenharmony_ci				      AU1550_OHCICFG);
6138c2ecf20Sopenharmony_ci		break;
6148c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1200:
6158c2ecf20Sopenharmony_ci		au1200_usb_init();
6168c2ecf20Sopenharmony_ci		break;
6178c2ecf20Sopenharmony_ci	case ALCHEMY_CPU_AU1300:
6188c2ecf20Sopenharmony_ci		au1300_usb_init();
6198c2ecf20Sopenharmony_ci		break;
6208c2ecf20Sopenharmony_ci	}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	if (!ret)
6238c2ecf20Sopenharmony_ci		register_syscore_ops(&alchemy_usb_pm_ops);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	return ret;
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ciarch_initcall(alchemy_usb_init);
628