summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/mips/lantiq/xway/reset.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index dd1aaaf8e3e6..4b52ce6d38f8 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -60,6 +60,37 @@
#define RCU_BOOT_SEL(x) ((x >> 18) & 0x7)
#define RCU_BOOT_SEL_XRX200(x) (((x >> 17) & 0xf) | ((x >> 8) & 0x10))
+/* dwc2 USB configuration registers */
+#define RCU_USB1CFG 0x0018
+#define RCU_USB2CFG 0x0034
+
+/* USB DMA endianness bits */
+#define RCU_USBCFG_HDSEL_BIT BIT(11)
+#define RCU_USBCFG_HOST_END_BIT BIT(10)
+#define RCU_USBCFG_SLV_END_BIT BIT(9)
+
+/* USB reset bits */
+#define RCU_USBRESET 0x0010
+
+#define USBRESET_BIT BIT(4)
+
+#define RCU_USBRESET2 0x0048
+
+#define USB1RESET_BIT BIT(4)
+#define USB2RESET_BIT BIT(5)
+
+#define RCU_CFG1A 0x0038
+#define RCU_CFG1B 0x003C
+
+/* USB PMU devices */
+#define PMU_AHBM BIT(15)
+#define PMU_USB0 BIT(6)
+#define PMU_USB1 BIT(27)
+
+/* USB PHY PMU devices */
+#define PMU_USB0_P BIT(0)
+#define PMU_USB1_P BIT(26)
+
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
static struct device_node *ltq_rcu_np;
@@ -272,6 +303,45 @@ static void ltq_machine_power_off(void)
unreachable();
}
+static void ltq_usb_init(void)
+{
+ /* Power for USB cores 1 & 2 */
+ ltq_pmu_enable(PMU_AHBM);
+ ltq_pmu_enable(PMU_USB0);
+ ltq_pmu_enable(PMU_USB1);
+
+ ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1A) | BIT(0), RCU_CFG1A);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_CFG1B) | BIT(0), RCU_CFG1B);
+
+ /* Enable USB PHY power for cores 1 & 2 */
+ ltq_pmu_enable(PMU_USB0_P);
+ ltq_pmu_enable(PMU_USB1_P);
+
+ /* Configure cores to host mode */
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_HDSEL_BIT,
+ RCU_USB1CFG);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USB2CFG) & ~RCU_USBCFG_HDSEL_BIT,
+ RCU_USB2CFG);
+
+ /* Select DMA endianness (Host-endian: big-endian) */
+ ltq_rcu_w32((ltq_rcu_r32(RCU_USB1CFG) & ~RCU_USBCFG_SLV_END_BIT)
+ | RCU_USBCFG_HOST_END_BIT, RCU_USB1CFG);
+ ltq_rcu_w32(ltq_rcu_r32((RCU_USB2CFG) & ~RCU_USBCFG_SLV_END_BIT)
+ | RCU_USBCFG_HOST_END_BIT, RCU_USB2CFG);
+
+ /* Hard reset USB state machines */
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) | USBRESET_BIT, RCU_USBRESET);
+ udelay(50 * 1000);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET) & ~USBRESET_BIT, RCU_USBRESET);
+
+ /* Soft reset USB state machines */
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+ | USB1RESET_BIT | USB2RESET_BIT, RCU_USBRESET2);
+ udelay(50 * 1000);
+ ltq_rcu_w32(ltq_rcu_r32(RCU_USBRESET2)
+ & ~(USB1RESET_BIT | USB2RESET_BIT), RCU_USBRESET2);
+}
+
static int __init mips_reboot_setup(void)
{
struct resource res;
@@ -295,6 +365,10 @@ static int __init mips_reboot_setup(void)
if (!ltq_rcu_membase)
panic("Failed to remap core memory");
+ if (of_machine_is_compatible("lantiq,ar9") ||
+ of_machine_is_compatible("lantiq,vr9"))
+ ltq_usb_init();
+
_machine_restart = ltq_machine_restart;
_machine_halt = ltq_machine_halt;
pm_power_off = ltq_machine_power_off;