summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2022-06-12 14:31:55 +0000
committercinap_lenrek <cinap_lenrek@felloff.net>2022-06-12 14:31:55 +0000
commitf1f5045b2e3c0ce6540abad3cad88f5e69a59a3c (patch)
tree6368777ad5617728a93d39dd28fe0a8bf87a9eb5 /sys
parent1d81f7eacbe2db017f49cf5646c7671f0581f170 (diff)
imx8/usbxhci: bring usb out of reset
do all the magic dwc3 specific initalization as well as reset the hub and power on the phys. with this, "usb start" command is not needed anymore from u-boot.
Diffstat (limited to 'sys')
-rw-r--r--sys/src/9/imx8/usbxhciimx.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c
index 6eebb3dfe..18b6efc00 100644
--- a/sys/src/9/imx8/usbxhciimx.c
+++ b/sys/src/9/imx8/usbxhciimx.c
@@ -1785,6 +1785,92 @@ clkenable(int i, int on)
setclkgate(clk, on);
}
+static void
+hubreset(int on)
+{
+ /* gpio registers */
+ enum {
+ GPIO_DR = 0x00/4,
+ GPIO_GDIR = 0x04/4,
+ GPIO_PSR = 0x08/4,
+ GPIO_ICR1 = 0x0C/4,
+ GPIO_ICR2 = 0x10/4,
+ GPIO_IMR = 0x14/4,
+ GPIO_ISR = 0x18/4,
+ GPIO_EDGE_SEL = 0x1C/4,
+ };
+ static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000);
+
+ gpio1[GPIO_GDIR] |= 1<<14; /* output */
+ if(on)
+ gpio1[GPIO_DR] |= 1<<14;
+ else
+ gpio1[GPIO_DR] &= ~(1<<14);
+}
+
+static void
+powerup(int i)
+{
+ /* power gating controller registers */
+ enum {
+ GPC_PGC_CPU_0_1_MAPPING = 0xEC/4,
+ GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4,
+ USB_OTG1_SW_PUP_REQ = 1<<2,
+ };
+ static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000);
+
+ gpc[GPC_PGC_CPU_0_1_MAPPING] = 0x0000FFFF;
+
+ gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] |= (USB_OTG1_SW_PUP_REQ<<i);
+ while(gpc[GPC_PGC_PU_PGC_SW_PUP_REQ] & (USB_OTG1_SW_PUP_REQ<<i))
+ ;
+
+ gpc[GPC_PGC_CPU_0_1_MAPPING] = 0;
+}
+
+static void
+phyinit(u32int *reg)
+{
+ enum {
+ PHY_CTRL0 = 0x0/4,
+ CTRL0_REF_SSP_EN = 1<<2,
+ PHY_CTRL1 = 0x4/4,
+ CTRL1_RESET = 1<<0,
+ CTRL1_ATERESET = 1<<3,
+ CTRL1_VDATSRCENB0 = 1<<19,
+ CTRL1_VDATDETEBB0 = 1<<20,
+ PHY_CTRL2 = 0x8/4,
+ CTRL2_TXENABLEN0 = 1<<8,
+ };
+ reg[PHY_CTRL1] = (reg[PHY_CTRL1] & ~(CTRL1_VDATSRCENB0 | CTRL1_VDATDETEBB0)) | CTRL1_RESET | CTRL1_ATERESET;
+ reg[PHY_CTRL0] |= CTRL0_REF_SSP_EN;
+ reg[PHY_CTRL2] |= CTRL2_TXENABLEN0;
+ reg[PHY_CTRL1] &= ~(CTRL1_RESET | CTRL1_ATERESET);
+}
+
+static void
+coreinit(u32int *reg)
+{
+ enum {
+ GCTL = 0xC110/4,
+ PWRDNSCALE_SHIFT = 19,
+ PWRDNSCALE_MASK = 0x3FFF << PWRDNSCALE_SHIFT,
+ PRTCAPDIR_SHIFT = 12,
+ PRTCAPDIR_MASK = 3 << PRTCAPDIR_SHIFT,
+ DISSCRAMBLE = 1<<3,
+ DSBLCLKGTNG = 1<<0,
+
+ GFLADJ = 0xC630/4,
+ GFLADJ_30MHZ_SDBND_SEL = 1<<7,
+ GFLADJ_30MHZ_SHIFT = 0,
+ GFLADJ_30MHZ_MASK = 0x3F << GFLADJ_30MHZ_SHIFT,
+
+ };
+ reg[GCTL] &= ~(PWRDNSCALE_MASK | DISSCRAMBLE | DSBLCLKGTNG | PRTCAPDIR_MASK);
+ reg[GCTL] |= 2<<PWRDNSCALE_SHIFT | 1<<PRTCAPDIR_SHIFT;
+ reg[GFLADJ] = (reg[GFLADJ] & ~GFLADJ_30MHZ_MASK) | 0x20<<GFLADJ_30MHZ_SHIFT | GFLADJ_30MHZ_SDBND_SEL;
+}
+
static int
reset(Hci *hp)
{
@@ -1808,13 +1894,31 @@ reset(Hci *hp)
Found:
if(i == 0){
+ static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000);
+ enum {
+ IOMUXC_CTL_PAD_GPIO1_IO13 = 0x5C/4, /* for gpio1 13 */
+ IOMUXC_CTL_PAD_GPIO1_IO14 = 0x60/4, /* for gpio1 14 */
+
+ IOMUXC_SW_PAD_CTRL_PAD_GPIO1_IO14 = 0x2C8/4,
+ };
+ iomuxc[IOMUXC_CTL_PAD_GPIO1_IO13] = 1;
+ iomuxc[IOMUXC_CTL_PAD_GPIO1_IO14] = 0;
+ iomuxc[IOMUXC_SW_PAD_CTRL_PAD_GPIO1_IO14] = 0x16;
+
+ hubreset(0);
+ microdelay(500);
+ hubreset(1);
+
for(i = 0; i < nelem(ctlrs); i++) clkenable(i, 0);
setclkrate("ccm_usb_bus_clk_root", "system_pll2_div2", 500*Mhz);
setclkrate("ccm_usb_core_ref_clk_root", "system_pll1_div8", 100*Mhz);
setclkrate("ccm_usb_phy_ref_clk_root", "system_pll1_div8", 100*Mhz);
i = 0;
}
+ powerup(i);
clkenable(i, 1);
+ phyinit(&ctlr->mmio[0xF0040/4]);
+ coreinit(ctlr->mmio);
hp->init = init;
hp->dump = dump;