Commit 26cfdbe3 authored by John Crispin's avatar John Crispin Committed by Ralf Baechle

MIPS: lantiq: Initialize the USB core on boot

There is a DWC2 USB core in these SoCs. To make USB work we need to first
reset and power the state machine. These are SoC specific registers and
not part of the actual USB core.
Signed-off-by: default avatarAntti Seppälä <a.seppala@gmail.com>
Signed-off-by: default avatarJohn Crispin <blogic@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/11449/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 1601078d
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment