diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-06-11 21:12:04 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-06-11 21:12:04 +0000 |
commit | 931ae0cfebeb46892406efc7468636e59f8110a9 (patch) | |
tree | ae94bfb7f75e49c986ae6968291d919623e17e90 /sys/src | |
parent | 276f2039a9bceb4bc23b0fa1ce3169057aac405e (diff) |
imx8: mainscreen turn on!
supports the lcd panel and adds alot of infrastructure
like for the ccm clock module and the i2c controllers.
Diffstat (limited to 'sys/src')
-rw-r--r-- | sys/src/9/imx8/ccm.c | 1357 | ||||
-rw-r--r-- | sys/src/9/imx8/etherimx.c | 10 | ||||
-rw-r--r-- | sys/src/9/imx8/fns.h | 9 | ||||
-rw-r--r-- | sys/src/9/imx8/lcd.c | 949 | ||||
-rw-r--r-- | sys/src/9/imx8/main.c | 12 | ||||
-rw-r--r-- | sys/src/9/imx8/mem.h | 6 | ||||
-rw-r--r-- | sys/src/9/imx8/mkfile | 8 | ||||
-rw-r--r-- | sys/src/9/imx8/mmu.c | 29 | ||||
-rw-r--r-- | sys/src/9/imx8/reform | 6 | ||||
-rw-r--r-- | sys/src/9/imx8/screen.c | 341 | ||||
-rw-r--r-- | sys/src/9/imx8/screen.h | 32 | ||||
-rw-r--r-- | sys/src/9/imx8/uartimx.c | 18 | ||||
-rw-r--r-- | sys/src/9/imx8/usbxhciimx.c | 20 |
13 files changed, 2774 insertions, 23 deletions
diff --git a/sys/src/9/imx8/ccm.c b/sys/src/9/imx8/ccm.c new file mode 100644 index 000000000..ffec22d52 --- /dev/null +++ b/sys/src/9/imx8/ccm.c @@ -0,0 +1,1357 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" + +static u32int *regs = (u32int*)(VIRTIO + 0x380000); +static u32int *anatop = (u32int*)(VIRTIO + 0x360000); + +enum { + /* input clocks */ + ARM_PLL_CLK = 12, + GPU_PLL_CLK, + VPU_PLL_CLK, + DRAM_PLL1_CLK, + SYSTEM_PLL1_CLK, + SYSTEM_PLL1_DIV2, + SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_DIV4, + SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_DIV6, + SYSTEM_PLL1_DIV8, + SYSTEM_PLL1_DIV10, + SYSTEM_PLL1_DIV20, + SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV2, + SYSTEM_PLL2_DIV3, + SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_DIV5, + SYSTEM_PLL2_DIV6, + SYSTEM_PLL2_DIV8, + SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV20, + SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, + AUDIO_PLL2_CLK, + VIDEO_PLL1_CLK, + VIDEO_PLL2_CLK, + + OSC_32K_REF_CLK, + OSC_25M_REF_CLK, + OSC_27M_REF_CLK, + EXT_CLK_1, + EXT_CLK_2, + EXT_CLK_3, + EXT_CLK_4, + + /* root clocks (slices) */ + ARM_A53_CLK_ROOT = 0, + ARM_M4_CLK_ROOT = 1, + VPU_A53_CLK_ROOT = 2, + GPU_CORE_CLK_ROOT = 3, + GPU_SHADER_CLK_ROOT = 4, + + MAIN_AXI_CLK_ROOT = 16, + ENET_AXI_CLK_ROOT = 17, + NAND_USDHC_BUS_CLK_ROOT = 18, + VPU_BUS_CLK_ROOT = 19, + DISPLAY_AXI_CLK_ROOT = 20, + DISPLAY_APB_CLK_ROOT = 21, + DISPLAY_RTRM_CLK_ROOT = 22, + USB_BUS_CLK_ROOT = 23, + GPU_AXI_CLK_ROOT = 24, + GPU_AHB_CLK_ROOT = 25, + NOC_CLK_ROOT = 26, + NOC_APB_CLK_ROOT = 27, + + AHB_CLK_ROOT = 32, + IPG_CLK_ROOT = 33, + AUDIO_AHB_CLK_ROOT = 34, + AUDIO_IPG_CLK_ROOT = 35, + MIPI_DSI_ESC_RX_CLK_ROOT = 36, + MIPI_DSI_ESC_CLK_ROOT = 37, + + DRAM_ALT_CLK_ROOT = 64, + DRAM_APB_CLK_ROOT = 65, + VPU_G1_CLK_ROOT = 66, + VPU_G2_CLK_ROOT = 67, + DISPLAY_DTRC_CLK_ROOT = 68, + DISPLAY_DC8000_CLK_ROOT = 69, + PCIE1_CTRL_CLK_ROOT = 70, + PCIE1_PHY_CLK_ROOT = 71, + PCIE1_AUX_CLK_ROOT = 72, + DC_PIXEL_CLK_ROOT = 73, + LCDIF_PIXEL_CLK_ROOT = 74, + SAI1_CLK_ROOT = 75, + SAI2_CLK_ROOT = 76, + SAI3_CLK_ROOT = 77, + SAI4_CLK_ROOT = 78, + SAI5_CLK_ROOT = 79, + SAI6_CLK_ROOT = 80, + SPDIF1_CLK_ROOT = 81, + SPDIF2_CLK_ROOT = 82, + ENET_REF_CLK_ROOT = 83, + ENET_TIMER_CLK_ROOT = 84, + ENET_PHY_REF_CLK_ROOT = 85, + NAND_CLK_ROOT = 86, + QSPI_CLK_ROOT = 87, + USDHC1_CLK_ROOT = 88, + USDHC2_CLK_ROOT = 89, + I2C1_CLK_ROOT = 90, + I2C2_CLK_ROOT = 91, + I2C3_CLK_ROOT = 92, + I2C4_CLK_ROOT = 93, + UART1_CLK_ROOT = 94, + UART2_CLK_ROOT = 95, + UART3_CLK_ROOT = 96, + UART4_CLK_ROOT = 97, + USB_CORE_REF_CLK_ROOT = 98, + USB_PHY_REF_CLK_ROOT = 99, + GIC_CLK_ROOT = 100, + ECSPI1_CLK_ROOT = 101, + ECSPI2_CLK_ROOT = 102, + PWM1_CLK_ROOT = 103, + PWM2_CLK_ROOT = 104, + PWM3_CLK_ROOT = 105, + PWM4_CLK_ROOT = 106, + GPT1_CLK_ROOT = 107, + GPT2_CLK_ROOT = 108, + GPT3_CLK_ROOT = 109, + GPT4_CLK_ROOT = 110, + GPT5_CLK_ROOT = 111, + GPT6_CLK_ROOT = 112, + TRACE_CLK_ROOT = 113, + WDOG_CLK_ROOT = 114, + WRCLK_CLK_ROOT = 115, + IPP_DO_CLKO1 = 116, + IPP_DO_CLKO2 = 117, + MIPI_DSI_CORE_CLK_ROOT = 118, + MIPI_DSI_PHY_REF_CLK_ROOT = 119, + MIPI_DSI_DBI_CLK_ROOT = 120, + OLD_MIPI_DSI_ESC_CLK_ROOT = 121, + MIPI_CSI1_CORE_CLK_ROOT = 122, + MIPI_CSI1_PHY_REF_CLK_ROOT = 123, + MIPI_CSI1_ESC_CLK_ROOT = 124, + MIPI_CSI2_CORE_CLK_ROOT = 125, + MIPI_CSI2_PHY_REF_CLK_ROOT = 126, + MIPI_CSI2_ESC_CLK_ROOT = 127, + PCIE2_CTRL_CLK_ROOT = 128, + PCIE2_PHY_CLK_ROOT = 129, + PCIE2_AUX_CLK_ROOT = 130, + ECSPI3_CLK_ROOT = 131, + OLD_MIPI_DSI_ESC_RX_CLK_ROOT = 132, + DISPLAY_HDMI_CLK_ROOT = 133, +}; + +static int input_clk_freq[] = { + [ARM_PLL_CLK] 1600*Mhz, + [GPU_PLL_CLK] 1600*Mhz, + [VPU_PLL_CLK] 800*Mhz, + [DRAM_PLL1_CLK] 800*Mhz, + [SYSTEM_PLL1_CLK] 800*Mhz, + [SYSTEM_PLL1_DIV2] 400*Mhz, + [SYSTEM_PLL1_DIV3] 266*Mhz, + [SYSTEM_PLL1_DIV4] 200*Mhz, + [SYSTEM_PLL1_DIV5] 160*Mhz, + [SYSTEM_PLL1_DIV6] 133*Mhz, + [SYSTEM_PLL1_DIV8] 100*Mhz, + [SYSTEM_PLL1_DIV10] 80*Mhz, + [SYSTEM_PLL1_DIV20] 40*Mhz, + [SYSTEM_PLL2_CLK] 1000*Mhz, + [SYSTEM_PLL2_DIV2] 500*Mhz, + [SYSTEM_PLL2_DIV3] 333*Mhz, + [SYSTEM_PLL2_DIV4] 250*Mhz, + [SYSTEM_PLL2_DIV5] 200*Mhz, + [SYSTEM_PLL2_DIV6] 166*Mhz, + [SYSTEM_PLL2_DIV8] 125*Mhz, + [SYSTEM_PLL2_DIV10] 100*Mhz, + [SYSTEM_PLL2_DIV20] 50*Mhz, + [SYSTEM_PLL3_CLK] 1000*Mhz, + [AUDIO_PLL1_CLK] 650*Mhz, + [AUDIO_PLL2_CLK] 650*Mhz, + [VIDEO_PLL1_CLK] 594*Mhz, + [VIDEO_PLL2_CLK] 600*Mhz, + [OSC_32K_REF_CLK] 32000, + [OSC_25M_REF_CLK] 25*Mhz, + [OSC_27M_REF_CLK] 27*Mhz, + [EXT_CLK_1] 133*Mhz, + [EXT_CLK_2] 133*Mhz, + [EXT_CLK_3] 133*Mhz, + [EXT_CLK_4] 133*Mhz, +}; + +static char *input_clk_name[] = { + [ARM_PLL_CLK] "arm_pll_clk", + [GPU_PLL_CLK] "gpu_pll_clk", + [VPU_PLL_CLK] "vpu_pll_clk", + [DRAM_PLL1_CLK] "dram_pll1_clk", + [SYSTEM_PLL1_CLK] "system_pll1_clk", + [SYSTEM_PLL1_DIV2] "system_pll1_div2", + [SYSTEM_PLL1_DIV3] "system_pll1_div3", + [SYSTEM_PLL1_DIV4] "system_pll1_div4", + [SYSTEM_PLL1_DIV5] "system_pll1_div5", + [SYSTEM_PLL1_DIV6] "system_pll1_div6", + [SYSTEM_PLL1_DIV8] "system_pll1_div8", + [SYSTEM_PLL1_DIV10] "system_pll1_div10", + [SYSTEM_PLL1_DIV20] "system_pll1_div20", + [SYSTEM_PLL2_CLK] "system_pll2_clk", + [SYSTEM_PLL2_DIV2] "system_pll2_div2", + [SYSTEM_PLL2_DIV3] "system_pll2_div3", + [SYSTEM_PLL2_DIV4] "system_pll2_div4", + [SYSTEM_PLL2_DIV5] "system_pll2_div5", + [SYSTEM_PLL2_DIV6] "system_pll2_div6", + [SYSTEM_PLL2_DIV8] "system_pll2_div8", + [SYSTEM_PLL2_DIV10] "system_pll2_div10", + [SYSTEM_PLL2_DIV20] "system_pll2_div20", + [SYSTEM_PLL3_CLK] "system_pll3_clk", + [AUDIO_PLL1_CLK] "audio_pll1_clk", + [AUDIO_PLL2_CLK] "audio_pll2_clk", + [VIDEO_PLL1_CLK] "video_pll1_clk", + [VIDEO_PLL2_CLK] "video_pll2_clk", + [OSC_32K_REF_CLK] "osc_32k_ref_clk", + [OSC_25M_REF_CLK] "osc_25m_ref_clk", + [OSC_27M_REF_CLK] "osc_27m_ref_clk", + [EXT_CLK_1] "ext_clk_1", + [EXT_CLK_2] "ext_clk_2", + [EXT_CLK_3] "ext_clk_3", + [EXT_CLK_4] "ext_clk_4", +}; + +static char *root_clk_name[] = { + [ARM_A53_CLK_ROOT] "ccm_arm_a53_clk_root", + [ARM_M4_CLK_ROOT] "ccm_arm_m4_clk_root", + [VPU_A53_CLK_ROOT] "ccm_vpu_a53_clk_root", + [GPU_CORE_CLK_ROOT] "ccm_gpu_core_clk_root", + [GPU_SHADER_CLK_ROOT] "ccm_gpu_shader_clk_root", + [MAIN_AXI_CLK_ROOT] "ccm_main_axi_clk_root", + [ENET_AXI_CLK_ROOT] "ccm_enet_axi_clk_root", + [NAND_USDHC_BUS_CLK_ROOT] "ccm_nand_usdhc_bus_clk_root", + [VPU_BUS_CLK_ROOT] "ccm_vpu_bus_clk_root", + [DISPLAY_AXI_CLK_ROOT] "ccm_display_axi_clk_root", + [DISPLAY_APB_CLK_ROOT] "ccm_display_apb_clk_root", + [DISPLAY_RTRM_CLK_ROOT] "ccm_display_rtrm_clk_root", + [USB_BUS_CLK_ROOT] "ccm_usb_bus_clk_root", + [GPU_AXI_CLK_ROOT] "ccm_gpu_axi_clk_root", + [GPU_AHB_CLK_ROOT] "ccm_gpu_ahb_clk_root", + [NOC_CLK_ROOT] "ccm_noc_clk_root", + [NOC_APB_CLK_ROOT] "ccm_noc_apb_clk_root", + [AHB_CLK_ROOT] "ccm_ahb_clk_root", + [IPG_CLK_ROOT] "ccm_ipg_clk_root", + [AUDIO_AHB_CLK_ROOT] "ccm_audio_ahb_clk_root", + [AUDIO_IPG_CLK_ROOT] "ccm_audio_ipg_clk_root", + [MIPI_DSI_ESC_RX_CLK_ROOT] "ccm_mipi_dsi_esc_rx_clk_root", + [MIPI_DSI_ESC_CLK_ROOT] "ccm_mipi_dsi_esc_clk_root", + [DRAM_ALT_CLK_ROOT] "ccm_dram_alt_clk_root", + [DRAM_APB_CLK_ROOT] "ccm_dram_apb_clk_root", + [VPU_G1_CLK_ROOT] "ccm_vpu_g1_clk_root", + [VPU_G2_CLK_ROOT] "ccm_vpu_g2_clk_root", + [DISPLAY_DTRC_CLK_ROOT] "ccm_display_dtrc_clk_root", + [DISPLAY_DC8000_CLK_ROOT] "ccm_display_dc8000_clk_root", + [PCIE1_CTRL_CLK_ROOT] "ccm_pcie1_ctrl_clk_root", + [PCIE1_PHY_CLK_ROOT] "ccm_pcie1_phy_clk_root", + [PCIE1_AUX_CLK_ROOT] "ccm_pcie1_aux_clk_root", + [DC_PIXEL_CLK_ROOT] "ccm_dc_pixel_clk_root", + [LCDIF_PIXEL_CLK_ROOT] "ccm_lcdif_pixel_clk_root", + [SAI1_CLK_ROOT] "ccm_sai1_clk_root", + [SAI2_CLK_ROOT] "ccm_sai2_clk_root", + [SAI3_CLK_ROOT] "ccm_sai3_clk_root", + [SAI4_CLK_ROOT] "ccm_sai4_clk_root", + [SAI5_CLK_ROOT] "ccm_sai5_clk_root", + [SAI6_CLK_ROOT] "ccm_sai6_clk_root", + [SPDIF1_CLK_ROOT] "ccm_spdif1_clk_root", + [SPDIF2_CLK_ROOT] "ccm_spdif2_clk_root", + [ENET_REF_CLK_ROOT] "ccm_enet_ref_clk_root", + [ENET_TIMER_CLK_ROOT] "ccm_enet_timer_clk_root", + [ENET_PHY_REF_CLK_ROOT] "ccm_enet_phy_ref_clk_root", + [NAND_CLK_ROOT] "ccm_nand_clk_root", + [QSPI_CLK_ROOT] "ccm_qspi_clk_root", + [USDHC1_CLK_ROOT] "ccm_usdhc1_clk_root", + [USDHC2_CLK_ROOT] "ccm_usdhc2_clk_root", + [I2C1_CLK_ROOT] "ccm_i2c1_clk_root", + [I2C2_CLK_ROOT] "ccm_i2c2_clk_root", + [I2C3_CLK_ROOT] "ccm_i2c3_clk_root", + [I2C4_CLK_ROOT] "ccm_i2c4_clk_root", + [UART1_CLK_ROOT] "ccm_uart1_clk_root", + [UART2_CLK_ROOT] "ccm_uart2_clk_root", + [UART3_CLK_ROOT] "ccm_uart3_clk_root", + [UART4_CLK_ROOT] "ccm_uart4_clk_root", + [USB_CORE_REF_CLK_ROOT] "ccm_usb_core_ref_clk_root", + [USB_PHY_REF_CLK_ROOT] "ccm_usb_phy_ref_clk_root", + [GIC_CLK_ROOT] "ccm_gic_clk_root", + [ECSPI1_CLK_ROOT] "ccm_ecspi1_clk_root", + [ECSPI2_CLK_ROOT] "ccm_ecspi2_clk_root", + [PWM1_CLK_ROOT] "ccm_pwm1_clk_root", + [PWM2_CLK_ROOT] "ccm_pwm2_clk_root", + [PWM3_CLK_ROOT] "ccm_pwm3_clk_root", + [PWM4_CLK_ROOT] "ccm_pwm4_clk_root", + [GPT1_CLK_ROOT] "ccm_gpt1_clk_root", + [GPT2_CLK_ROOT] "ccm_gpt2_clk_root", + [GPT3_CLK_ROOT] "ccm_gpt3_clk_root", + [GPT4_CLK_ROOT] "ccm_gpt4_clk_root", + [GPT5_CLK_ROOT] "ccm_gpt5_clk_root", + [GPT6_CLK_ROOT] "ccm_gpt6_clk_root", + [TRACE_CLK_ROOT] "ccm_trace_clk_root", + [WDOG_CLK_ROOT] "ccm_wdog_clk_root", + [WRCLK_CLK_ROOT] "ccm_wrclk_clk_root", + [IPP_DO_CLKO1] "ccm_ipp_do_clko1", + [IPP_DO_CLKO2] "ccm_ipp_do_clko2", + [MIPI_DSI_CORE_CLK_ROOT] "ccm_mipi_dsi_core_clk_root", + [MIPI_DSI_PHY_REF_CLK_ROOT] "ccm_mipi_dsi_phy_ref_clk_root", + [MIPI_DSI_DBI_CLK_ROOT] "ccm_mipi_dsi_dbi_clk_root", + [OLD_MIPI_DSI_ESC_CLK_ROOT] "ccm_old_mipi_dsi_esc_clk_root", + [MIPI_CSI1_CORE_CLK_ROOT] "ccm_mipi_csi1_core_clk_root", + [MIPI_CSI1_PHY_REF_CLK_ROOT] "ccm_mipi_csi1_phy_ref_clk_root", + [MIPI_CSI1_ESC_CLK_ROOT] "ccm_mipi_csi1_esc_clk_root", + [MIPI_CSI2_CORE_CLK_ROOT] "ccm_mipi_csi2_core_clk_root", + [MIPI_CSI2_PHY_REF_CLK_ROOT] "ccm_mipi_csi2_phy_ref_clk_root", + [MIPI_CSI2_ESC_CLK_ROOT] "ccm_mipi_csi2_esc_clk_root", + [PCIE2_CTRL_CLK_ROOT] "ccm_pcie2_ctrl_clk_root", + [PCIE2_PHY_CLK_ROOT] "ccm_pcie2_phy_clk_root", + [PCIE2_AUX_CLK_ROOT] "ccm_pcie2_aux_clk_root", + [ECSPI3_CLK_ROOT] "ccm_ecspi3_clk_root", + [OLD_MIPI_DSI_ESC_RX_CLK_ROOT] "ccm_old_mipi_dsi_esc_rx_clk_root", + [DISPLAY_HDMI_CLK_ROOT] "ccm_display_hdmi_clk_root", +}; + +static uchar root_clk_input_mux[] = { +[ARM_A53_CLK_ROOT*8] + OSC_25M_REF_CLK, ARM_PLL_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL3_CLK, +[ARM_M4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, +[VPU_A53_CLK_ROOT*8] + OSC_25M_REF_CLK, ARM_PLL_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, VPU_PLL_CLK, +[GPU_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, GPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[GPU_SHADER_CLK_ROOT*8] + OSC_25M_REF_CLK, GPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[MAIN_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV8, +[ENET_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV4, + SYSTEM_PLL2_DIV5, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, +[NAND_USDHC_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV5, + SYSTEM_PLL1_DIV6, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL1_CLK, +[VPU_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, VPU_PLL_CLK, AUDIO_PLL2_CLK, + SYSTEM_PLL3_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV8, +[DISPLAY_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL1_DIV20, AUDIO_PLL2_CLK, EXT_CLK_1, EXT_CLK_4, +[DISPLAY_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL1_DIV20, AUDIO_PLL2_CLK, EXT_CLK_1, EXT_CLK_3, +[DISPLAY_RTRM_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV2, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, EXT_CLK_2, EXT_CLK_3, +[USB_BUS_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[GPU_AXI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, GPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[GPU_AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, GPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NOC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NOC_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV3, + SYSTEM_PLL2_DIV5, SYSTEM_PLL1_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV2, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[AUDIO_AHB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL2_DIV6, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_ESC_RX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[DRAM_ALT_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV2, + SYSTEM_PLL2_DIV4, SYSTEM_PLL1_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL1_DIV3, +[DRAM_APB_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[VPU_G1_CLK_ROOT*8] + OSC_25M_REF_CLK, VPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, +[VPU_G2_CLK_ROOT*8] + OSC_25M_REF_CLK, VPU_PLL_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV8, SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, +[DISPLAY_DTRC_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL2_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV5, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, +[DISPLAY_DC8000_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL2_CLK, SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, + SYSTEM_PLL1_DIV5, VIDEO_PLL1_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, +[PCIE1_CTRL_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV4, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_DIV3, SYSTEM_PLL3_CLK, +[PCIE1_PHY_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL2_DIV2, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, SYSTEM_PLL1_DIV2, +[PCIE1_AUX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV4, +[DC_PIXEL_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, AUDIO_PLL1_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +[LCDIF_PIXEL_CLK_ROOT*8] + OSC_25M_REF_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, AUDIO_PLL1_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +[SAI1_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_1, EXT_CLK_2, +[SAI2_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SAI3_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[SAI4_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_1, EXT_CLK_2, +[SAI5_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SAI6_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[SPDIF1_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_2, EXT_CLK_3, +[SPDIF2_CLK_ROOT*8] + OSC_25M_REF_CLK, AUDIO_PLL1_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, + SYSTEM_PLL1_DIV6, OSC_27M_REF_CLK, EXT_CLK_3, EXT_CLK_4, +[ENET_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL1_DIV5, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, EXT_CLK_4, +[ENET_TIMER_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, VIDEO_PLL1_CLK, +[ENET_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV20, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV5, + SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, +[NAND_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV2, AUDIO_PLL1_CLK, SYSTEM_PLL1_DIV2, + AUDIO_PLL2_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, VIDEO_PLL1_CLK, +[QSPI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV8, +[USDHC1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV3, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV8, +[USDHC2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, + SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV3, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV8, +[I2C1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[I2C4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, AUDIO_PLL2_CLK, SYSTEM_PLL1_DIV6, +[UART1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[UART2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[UART3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[UART4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV10, + SYSTEM_PLL3_CLK, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[USB_CORE_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[USB_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV8, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL2_DIV5, EXT_CLK_2, EXT_CLK_3, AUDIO_PLL2_CLK, +[GIC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL2_DIV10, + SYSTEM_PLL1_CLK, EXT_CLK_2, EXT_CLK_4, AUDIO_PLL2_CLK, +[ECSPI1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[ECSPI2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[PWM1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_1, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_1, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_2, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[PWM4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV20, + SYSTEM_PLL3_CLK, EXT_CLK_2, SYSTEM_PLL1_DIV10, VIDEO_PLL1_CLK, +[GPT1_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, +[GPT2_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_2, +[GPT3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_3, +[GPT4_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_1, +[GPT5_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_2, +[GPT6_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV2, SYSTEM_PLL1_DIV20, + VIDEO_PLL1_CLK, SYSTEM_PLL1_DIV10, AUDIO_PLL1_CLK, EXT_CLK_3, +[TRACE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_DIV5, VPU_PLL_CLK, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, EXT_CLK_1, EXT_CLK_3, +[WDOG_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV6, SYSTEM_PLL1_DIV5, VPU_PLL_CLK, + SYSTEM_PLL2_DIV8, SYSTEM_PLL3_CLK, SYSTEM_PLL1_DIV10, SYSTEM_PLL2_DIV6, +[WRCLK_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV20, VPU_PLL_CLK, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV2, SYSTEM_PLL1_DIV8, +[IPP_DO_CLKO1*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_CLK, OSC_27M_REF_CLK, SYSTEM_PLL1_DIV4, + AUDIO_PLL2_CLK, SYSTEM_PLL2_DIV2, VPU_PLL_CLK, SYSTEM_PLL1_DIV10, +[IPP_DO_CLKO2*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV2, SYSTEM_PLL2_DIV6, + SYSTEM_PLL3_CLK, AUDIO_PLL1_CLK, VIDEO_PLL1_CLK, OSC_32K_REF_CLK, +[MIPI_DSI_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV8, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_DSI_DBI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI1_ESC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[MIPI_CSI2_CORE_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV3, SYSTEM_PLL2_DIV4, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI2_PHY_REF_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV3, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, EXT_CLK_2, AUDIO_PLL2_CLK, VIDEO_PLL1_CLK, +[MIPI_CSI2_ESC_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[PCIE2_CTRL_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV4, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV3, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_DIV2, SYSTEM_PLL2_DIV3, SYSTEM_PLL3_CLK, +[PCIE2_PHY_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL2_DIV2, EXT_CLK_1, + EXT_CLK_2, EXT_CLK_3, EXT_CLK_4, SYSTEM_PLL1_DIV2, +[PCIE2_AUX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL2_DIV20, SYSTEM_PLL3_CLK, + SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_DIV5, SYSTEM_PLL1_DIV4, +[ECSPI3_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV5, SYSTEM_PLL1_DIV20, SYSTEM_PLL1_DIV5, + SYSTEM_PLL1_CLK, SYSTEM_PLL3_CLK, SYSTEM_PLL2_DIV4, AUDIO_PLL2_CLK, +[OLD_MIPI_DSI_ESC_RX_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL2_DIV10, SYSTEM_PLL1_DIV10, SYSTEM_PLL1_CLK, + SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_3, AUDIO_PLL2_CLK, +[DISPLAY_HDMI_CLK_ROOT*8] + OSC_25M_REF_CLK, SYSTEM_PLL1_DIV4, SYSTEM_PLL2_DIV5, VPU_PLL_CLK, + SYSTEM_PLL1_CLK, SYSTEM_PLL2_CLK, SYSTEM_PLL3_CLK, EXT_CLK_4, +}; + +typedef struct Clock Clock; +struct Clock { + char *name; /* clock instance name */ + int root; /* root clock slice */ + int ccgr; /* clock gating register */ +}; + +static Clock clocks[] = { + { "aips_tz1.hclk", AHB_CLK_ROOT, 28 }, + { "ipmux1.master_clk", AHB_CLK_ROOT, 28 }, + { "ipmux1.slave_clk", IPG_CLK_ROOT, 28 }, + + { "aips_tz2.hclk", AHB_CLK_ROOT, 29 }, + { "ipmux2.master_clk", AHB_CLK_ROOT, 29 }, + { "ipmux2.slave_clk", AHB_CLK_ROOT, 29 }, + + { "aips_tz3.hclk", AHB_CLK_ROOT, 30 }, + { "ipmux3.master_clk", AHB_CLK_ROOT, 30 }, + { "ipmux3.slave_clk", IPG_CLK_ROOT, 30 }, + + { "apbhdma.hclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "apdhdma_sec.mst_hclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "rawnand.u_bch_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "u_bch_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "rawnand.u_gpmi_bch_input_gpmi_io_clk", NAND_CLK_ROOT, 48 }, + { "rawnand.U_gpmi_input_apb_clk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + + { "caam.aclk", AHB_CLK_ROOT }, + { "caam.ipg_clk", IPG_CLK_ROOT }, + { "caam.ipg_clk_s", IPG_CLK_ROOT }, + { "caam_exsc.aclk_exsc", AHB_CLK_ROOT }, + { "caam_mem.clk", AHB_CLK_ROOT }, + + { "cm4.cm4_cti_clk", ARM_M4_CLK_ROOT }, + { "cm4.cm4_fclk", ARM_M4_CLK_ROOT }, + { "cm4.cm4_hclk", ARM_M4_CLK_ROOT }, + { "cm4.dap_clk", AHB_CLK_ROOT }, + { "cm4.ipg_clk_nic", ARM_M4_CLK_ROOT }, + { "cm4.tcmc_hclk", ARM_M4_CLK_ROOT }, + { "cm4_mem.tcmc_hclk", ARM_M4_CLK_ROOT }, + { "cm4_sec.ipg_clk", IPG_CLK_ROOT }, + { "cm4_sec.ipg_clk_s", IPG_CLK_ROOT }, + { "cm4_sec.mst_hclk", ARM_M4_CLK_ROOT }, + + { "csi2_1.clk_vid", MIPI_CSI1_PHY_REF_CLK_ROOT }, + { "csi2_1.clk", MIPI_CSI1_CORE_CLK_ROOT, 101}, + { "csi2_1.clk_esc", MIPI_CSI1_ESC_CLK_ROOT, 101}, + { "csi2_1.pclk", MIPI_CSI1_CORE_CLK_ROOT }, + { "csi2_1.clk_ui", MIPI_CSI1_PHY_REF_CLK_ROOT, 101}, + + { "csi2_2.clk_vid", MIPI_CSI2_PHY_REF_CLK_ROOT }, + { "csi2_2.clk", MIPI_CSI2_CORE_CLK_ROOT, 102 }, + { "csi2_2.clk_esc", MIPI_CSI2_ESC_CLK_ROOT, 102 }, + { "csi2_2.pclk", MIPI_CSI2_CORE_CLK_ROOT }, + { "csi2_2.clk_ui", MIPI_CSI2_PHY_REF_CLK_ROOT, 102 }, + + { "csu.ipg_clk_s", IPG_CLK_ROOT, 3}, + + { "dap.dapclk_2_2", AHB_CLK_ROOT, 4}, + + { "ecspi1.ipg_clk", IPG_CLK_ROOT, 7}, + { "ecspi1.ipg_clk_per", ECSPI1_CLK_ROOT, 7}, + { "ecspi1.ipg_clk_s", IPG_CLK_ROOT, 7}, + + { "ecspi2.ipg_clk", IPG_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_per", ECSPI2_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_s", IPG_CLK_ROOT, 8}, + + { "ecspi2.ipg_clk", IPG_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_per", ECSPI2_CLK_ROOT, 8}, + { "ecspi2.ipg_clk_s", IPG_CLK_ROOT, 8}, + + { "ecspi3.ipg_clk", IPG_CLK_ROOT, 9}, + { "ecspi3.ipg_clk_per", ECSPI3_CLK_ROOT, 9}, + { "ecspi3.ipg_clk_s", IPG_CLK_ROOT, 9}, + + { "enet1.ipp_ind_mac0_txclk", ENET_REF_CLK_ROOT, 10 }, + { "enet1.ipg_clk", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_mac0", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_mac0_s", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_s", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.ipg_clk_time", ENET_TIMER_CLK_ROOT, 10 }, + { "enet1.mem.mac0_rxmem_clk", ENET_AXI_CLK_ROOT, 10 }, + { "enet1.mem.mac0_txmem_clk", ENET_AXI_CLK_ROOT, 10 }, + + { "gpio1.ipg_clk_s", IPG_CLK_ROOT, 11 }, + { "gpio2.ipg_clk_s", IPG_CLK_ROOT, 12 }, + { "gpio3.ipg_clk_s", IPG_CLK_ROOT, 13 }, + { "gpio4.ipg_clk_s", IPG_CLK_ROOT, 14 }, + { "gpio5.ipg_clk_s", IPG_CLK_ROOT, 15 }, + + { "gpt1.ipg_clk", GPT1_CLK_ROOT, 16 }, + { "gpt1.ipg_clk_highfreq", GPT1_CLK_ROOT, 16 }, + { "gpt1.ipg_clk_s", GPT1_CLK_ROOT, 16 }, + + { "gpt2.ipg_clk", GPT2_CLK_ROOT, 17 }, + { "gpt2.ipg_clk_highfreq", GPT2_CLK_ROOT, 17 }, + { "gpt2.ipg_clk_s", GPT2_CLK_ROOT, 17 }, + + { "gpt3.ipg_clk", GPT3_CLK_ROOT, 18 }, + { "gpt3.ipg_clk_highfreq", GPT3_CLK_ROOT, 18 }, + { "gpt3.ipg_clk_s", GPT3_CLK_ROOT, 18 }, + + { "gpt4.ipg_clk", GPT4_CLK_ROOT, 19 }, + { "gpt4.ipg_clk_highfreq", GPT4_CLK_ROOT, 19 }, + { "gpt4.ipg_clk_s", GPT4_CLK_ROOT, 19 }, + + { "gpt5.ipg_clk", GPT5_CLK_ROOT, 20 }, + { "gpt5.ipg_clk_highfreq", GPT5_CLK_ROOT, 20 }, + { "gpt5.ipg_clk_s", GPT5_CLK_ROOT, 20 }, + + { "gpt6.ipg_clk", GPT6_CLK_ROOT, 21 }, + { "gpt6.ipg_clk_highfreq", GPT6_CLK_ROOT, 21 }, + { "gpt6.ipg_clk_s", GPT6_CLK_ROOT, 21 }, + + { "i2c1.ipg_clk_patref", I2C1_CLK_ROOT, 23 }, + { "i2c1.iph_clk_s", I2C1_CLK_ROOT, 23 }, + + { "i2c2.ipg_clk_patref", I2C2_CLK_ROOT, 24 }, + { "i2c2.iph_clk_s", I2C2_CLK_ROOT, 24 }, + + { "i2c3.ipg_clk_patref", I2C3_CLK_ROOT, 25 }, + { "i2c3.iph_clk_s", I2C3_CLK_ROOT, 25 }, + + { "i2c4.ipg_clk_patref", I2C4_CLK_ROOT, 26 }, + { "i2c4.iph_clk_s", I2C4_CLK_ROOT, 26 }, + + { "iomuxc.ipg_clk_s", IPG_CLK_ROOT, 27 }, + { "iomuxc_gpr.ipg_clk_s", IPG_CLK_ROOT, 27 }, + { "iomux.ipt_clk_io", IPG_CLK_ROOT, 27 }, + + { "lcdif.pix_clk", LCDIF_PIXEL_CLK_ROOT }, + { "lcdif.apb_clk", MAIN_AXI_CLK_ROOT }, + + { "disp.apb_clk", DISPLAY_APB_CLK_ROOT, 93 }, + { "disp.axi_clk", DISPLAY_AXI_CLK_ROOT, 93 }, + { "disp.rtrm_clk", DISPLAY_RTRM_CLK_ROOT, 93 }, + { "disp.dc8000_clk", DISPLAY_DC8000_CLK_ROOT, 93 }, + { "disp.dtrc_clk", DISPLAY_DTRC_CLK_ROOT }, + + { "mipi.CLKREF", MIPI_DSI_PHY_REF_CLK_ROOT }, + { "mipi.pclk", MAIN_AXI_CLK_ROOT }, + { "mipi.RxClkEsc", MIPI_DSI_ESC_RX_CLK_ROOT }, + { "mipi.TxClkEsc", MIPI_DSI_ESC_CLK_ROOT }, + { "mipi.core", MIPI_DSI_CORE_CLK_ROOT }, + { "mipi.ahb", MIPI_DSI_ESC_RX_CLK_ROOT }, + + { "mu.ipg_clk_dsp", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_mcu", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_s_dsp", IPG_CLK_ROOT, 33 }, + { "mu.ipg_clk_s_mcu", IPG_CLK_ROOT, 33 }, + + { "ocotp.ipg_clk", IPG_CLK_ROOT, 34 }, + { "ocotp.ipg_clk_s", IPG_CLK_ROOT, 34 }, + + { "ocram_ctrl.clk", MAIN_AXI_CLK_ROOT, 35 }, + { "ocram_excs.aclk_exsc", MAIN_AXI_CLK_ROOT, 35 }, + { "ocram_exsc.ipg_clk", IPG_CLK_ROOT, 35 }, + { "ocram_mem.clk", MAIN_AXI_CLK_ROOT, 35 }, + + { "ocram_ctrl_s.clk", AHB_CLK_ROOT, 36 }, + { "ocram_s_exsc.aclk_exsc", AHB_CLK_ROOT, 36 }, + { "ocram_s_exsc.ipg_clk", IPG_CLK_ROOT, 36 }, + { "ocram_s.mem_clk", AHB_CLK_ROOT, 36 }, + + { "pcie_clk_rst.auxclk", PCIE1_AUX_CLK_ROOT, 37 }, + { "pcie_clk_rst.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_clk_rst.slv_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_ctrl.mstr_aclk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_ctrl.slv_aclk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_exsc.aclk_exsc", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_exsc.ipg_clk", IPG_CLK_ROOT, 37 }, + { "pcie_mem.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + { "pcie_mem.slv_axi_clk", MAIN_AXI_CLK_ROOT, 37 }, + + { "pcie2_clk_rst.auxclk", PCIE2_AUX_CLK_ROOT, 100 }, + { "pcie2_clk_rst.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_clk_rst.slv_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_ctrl.mstr_aclk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_ctrl.slv_aclk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_exsc.aclk_exsc", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_exsc.ipg_clk", IPG_CLK_ROOT, 100 }, + { "pcie2_mem.mstr_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + { "pcie2_mem.slv_axi_clk", MAIN_AXI_CLK_ROOT, 100 }, + + { "pcie_phy.ref_alt_clk_p", PCIE1_PHY_CLK_ROOT }, + { "pcie2_phy.ref_alt_clk_p", PCIE2_PHY_CLK_ROOT }, + + { "perfmon1.apb_clk", IPG_CLK_ROOT, 38 }, + { "perfmon1.axi0_ACLK", MAIN_AXI_CLK_ROOT, 38 }, + + { "perfmon2.apb_clk", IPG_CLK_ROOT, 39 }, + { "perfmon1.axi0_ACLK", MAIN_AXI_CLK_ROOT, 39 }, + + { "pwm1.ipg_clk", PWM1_CLK_ROOT, 40 }, + { "pwm1.ipg_clk_high_freq", PWM1_CLK_ROOT, 40 }, + { "pwm1.ipg_clk_s", PWM1_CLK_ROOT, 40 }, + + { "pwm2.ipg_clk", PWM2_CLK_ROOT, 41 }, + { "pwm2.ipg_clk_high_freq", PWM2_CLK_ROOT, 41 }, + { "pwm2.ipg_clk_s", PWM2_CLK_ROOT, 41 }, + + { "pwm3.ipg_clk", PWM3_CLK_ROOT, 42 }, + { "pwm3.ipg_clk_high_freq", PWM3_CLK_ROOT, 42 }, + { "pwm3.ipg_clk_s", PWM3_CLK_ROOT, 42 }, + + { "pwm4.ipg_clk", PWM4_CLK_ROOT, 43 }, + { "pwm4.ipg_clk_high_freq", PWM4_CLK_ROOT, 43 }, + { "pwm4.ipg_clk_s", PWM4_CLK_ROOT, 43 }, + + { "qspi.ahb_clk", AHB_CLK_ROOT, 47 }, + { "qspi.ipg_clk", IPG_CLK_ROOT, 47 }, + { "qspi.ipg_clk_4xsfif", QSPI_CLK_ROOT, 47 }, + { "qspi.ipg_clk_s", IPG_CLK_ROOT, 47 }, + { "qspi_sec.ipg_clk", IPG_CLK_ROOT, 47 }, + { "qspi_sec.ipg_clk_s", IPG_CLK_ROOT, 47 }, + { "qspi_sec.mst_hclk", AHB_CLK_ROOT, 47 }, + + { "rdc.ipg_clk_s", IPG_CLK_ROOT, 49 }, + { "rdc.ipg_clk", IPG_CLK_ROOT, 49 }, + { "rdc_mem.ipg_clk", IPG_CLK_ROOT, 49 }, + + { "romcp.hclk", AHB_CLK_ROOT, 50 }, + { "romcp.hclk_reg", IPG_CLK_ROOT, 50 }, + { "romcp_mem.rom_CLK", AHB_CLK_ROOT, 50 }, + { "romcp_sec.mst_hclk", AHB_CLK_ROOT, 50 }, + + { "sai1.ipg_clk", AUDIO_IPG_CLK_ROOT, 51 }, + { "sai1.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 51 }, + { "sai1.ipg_clk_sai_mclk_1", SAI1_CLK_ROOT, 51 }, + { "sai1.ipt_clk_sai_bclk", SAI1_CLK_ROOT, 51 }, + { "sai1.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 51 }, + + { "sai2.ipg_clk", AUDIO_IPG_CLK_ROOT, 52 }, + { "sai2.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 52 }, + { "sai2.ipg_clk_sai_mclk_1", SAI2_CLK_ROOT, 52 }, + { "sai2.ipt_clk_sai_bclk", SAI2_CLK_ROOT, 52 }, + { "sai2.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 52 }, + + { "sai3.ipg_clk", AUDIO_IPG_CLK_ROOT, 53 }, + { "sai3.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 53 }, + { "sai3.ipg_clk_sai_mclk_1", SAI3_CLK_ROOT, 53 }, + { "sai3.ipt_clk_sai_bclk", SAI3_CLK_ROOT, 53 }, + { "sai3.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 53 }, + + { "sai4.ipg_clk", AUDIO_IPG_CLK_ROOT, 54 }, + { "sai4.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 54 }, + { "sai4.ipg_clk_sai_mclk_1", SAI4_CLK_ROOT, 54 }, + { "sai4.ipt_clk_sai_bclk", SAI4_CLK_ROOT, 54 }, + { "sai4.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 54 }, + + { "sai5.ipg_clk", AUDIO_IPG_CLK_ROOT, 55 }, + { "sai5.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 55 }, + { "sai5.ipg_clk_sai_mclk_1", SAI5_CLK_ROOT, 55 }, + { "sai5.ipt_clk_sai_bclk", SAI5_CLK_ROOT, 55 }, + { "sai5.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 55 }, + + { "sai6.ipg_clk", AUDIO_IPG_CLK_ROOT, 56 }, + { "sai6.ipg_clk_s", AUDIO_IPG_CLK_ROOT, 56 }, + { "sai6.ipg_clk_sai_mclk_1", SAI6_CLK_ROOT, 56 }, + { "sai6.ipt_clk_sai_bclk", SAI6_CLK_ROOT, 56 }, + { "sai6.ipt_clk_sai_bclk_b", SAI1_CLK_ROOT, 56 }, + + { "sctr.ipg_clk", IPG_CLK_ROOT, 57 }, + { "sctr.ipg_clk_s", IPG_CLK_ROOT, 57 }, + + { "sdma1.ips_hostctrl_clk", IPG_CLK_ROOT, 58 }, + { "sdma1.sdma_ap_ahb_clk", AHB_CLK_ROOT, 58 }, + { "sdma1.sdma_core_clk", IPG_CLK_ROOT, 58 }, + + { "sdma2.ips_hostctrl_clk", AUDIO_IPG_CLK_ROOT, 59 }, + { "sdma2.sdma_ap_ahb_clk", AUDIO_AHB_CLK_ROOT, 59 }, + { "sdma2.sdma_core_clk", AUDIO_IPG_CLK_ROOT, 59 }, + + { "sec_wrapper.clk", IPG_CLK_ROOT, 60 }, + + { "sema1.clk", IPG_CLK_ROOT, 61 }, + { "sema2.clk", IPG_CLK_ROOT, 62 }, + + { "sim_display.cm4clk", ARM_M4_CLK_ROOT }, + { "sim_display.mainclk", MAIN_AXI_CLK_ROOT, 63 }, + { "sim_display.mainclk_r", MAIN_AXI_CLK_ROOT, 63 }, + { "sim_enet.mainclk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_enet.mainclk_r", ENET_AXI_CLK_ROOT, 64 }, + { "sim_m.mainclk", AHB_CLK_ROOT, 65 }, + { "sim_m.mainclk_r", AHB_CLK_ROOT, 65 }, + { "sim_m.usdhcclk", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_m.usdhcclk_r", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_main.cm4clk", ARM_M4_CLK_ROOT }, + { "sim_main.enetclk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_main.mainclk", MAIN_AXI_CLK_ROOT, 66 }, + { "sim_main,mainclk_r", MAIN_AXI_CLK_ROOT, 66 }, + { "sim_main.per_mclk", AHB_CLK_ROOT, 65 }, + { "sim_main.per_sclk", AHB_CLK_ROOT, 67 }, + { "sim_main.usdhcclk", NAND_USDHC_BUS_CLK_ROOT, 65 }, + { "sim_main.wakeupclk", AHB_CLK_ROOT, 68 }, + { "sim_s.apbhdmaclk", NAND_USDHC_BUS_CLK_ROOT, 48 }, + { "sim_s.gpv4clk", ENET_AXI_CLK_ROOT, 64 }, + { "sim_s.mainclk", AHB_CLK_ROOT, 67 }, + { "sim_s.mainclk_r", AHB_CLK_ROOT, 67 }, + { "sim_s.weimclk", AHB_CLK_ROOT }, + { "sim_wakeup.mainclk", AHB_CLK_ROOT, 68 }, + { "sim_wakeup.mainclk_r", AHB_CLK_ROOT, 68 }, + { "pl301_audio.displayclk", MAIN_AXI_CLK_ROOT, 63 }, + + { "snvs_hs_wrapper.ipg_clk", IPG_CLK_ROOT, 71 }, + { "snvs_hs.wrapper.ipg_clk_s", IPG_CLK_ROOT, 71 }, + { "snvsmix.ipg_clk_root", IPG_CLK_ROOT }, + + { "spba1.ipg_clk", IPG_CLK_ROOT, 30 }, + { "spba1.ipg_clk_s", IPG_CLK_ROOT, 30 }, + + { "spba2.ipg_clk", AUDIO_IPG_CLK_ROOT }, + { "spba2.ipg_clk_s", AUDIO_IPG_CLK_ROOT }, + + { "spdif1.gclkw_t0", SPDIF1_CLK_ROOT}, + { "spdif1.ipg_clk_s", IPG_CLK_ROOT}, + { "spdif1.tx_clk", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk1", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk3", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk4", SPDIF1_CLK_ROOT}, + { "spdif1.tx_clk5", SPDIF1_CLK_ROOT}, + + { "spdif2.gclkw_t0", SPDIF2_CLK_ROOT}, + { "spdif2.ipg_clk_s", IPG_CLK_ROOT}, + { "spdif2.tx_clk", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk1", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk3", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk4", SPDIF2_CLK_ROOT}, + { "spdif2.tx_clk5", SPDIF2_CLK_ROOT}, + + { "coresight.DBGCLK", MAIN_AXI_CLK_ROOT, 72 }, + { "coresight.traceclkin", TRACE_CLK_ROOT, 72 }, + { "coresight_mem.cs_etf_clk", MAIN_AXI_CLK_ROOT, 72 }, + + { "uart1.ipg_clk", IPG_CLK_ROOT, 73 }, + { "uart1.ipg_clk_s", IPG_CLK_ROOT, 73 }, + { "uart1.ipg_perclk", UART1_CLK_ROOT, 73 }, + + { "uart2.ipg_clk", IPG_CLK_ROOT, 74 }, + { "uart2.ipg_clk_s", IPG_CLK_ROOT, 74 }, + { "uart2.ipg_perclk", UART2_CLK_ROOT, 74 }, + + { "uart3.ipg_clk", IPG_CLK_ROOT, 75 }, + { "uart3.ipg_clk_s", IPG_CLK_ROOT, 75 }, + { "uart3.ipg_perclk", UART3_CLK_ROOT, 75 }, + + { "uart4.ipg_clk", IPG_CLK_ROOT, 76 }, + { "uart4.ipg_clk_s", IPG_CLK_ROOT, 76 }, + { "uart4.ipg_perclk", UART4_CLK_ROOT, 76 }, + + { "usb.clk", IPG_CLK_ROOT, 22 }, /* HS */ + + { "usb1.ctrl", IPG_CLK_ROOT, 77 }, /* what is the root clock? */ + { "usb2.ctrl", IPG_CLK_ROOT, 78 }, + { "usb1.phy", IPG_CLK_ROOT, 79 }, /* what is the root clock? */ + { "usb2.phy", IPG_CLK_ROOT, 80 }, + + { "usdhc1.hclk", NAND_USDHC_BUS_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk", IPG_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk_s", IPG_CLK_ROOT, 81 }, + { "usdhc1.ipg_clk_perclk", USDHC1_CLK_ROOT, 81 }, + + { "usdhc2.hclk", NAND_USDHC_BUS_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk", IPG_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk_s", IPG_CLK_ROOT, 82 }, + { "usdhc2.ipg_clk_perclk", USDHC2_CLK_ROOT, 82 }, + + { "wdog1.ipg_clk", WDOG_CLK_ROOT, 83 }, + { "wdog1.ipg_clk_s", WDOG_CLK_ROOT, 83 }, + + { "wdog2.ipg_clk", WDOG_CLK_ROOT, 84 }, + { "wdog2.ipg_clk_s", WDOG_CLK_ROOT, 84 }, + + { "wdog3.ipg_clk", WDOG_CLK_ROOT, 85 }, + { "wdog3.ipg_clk_s", WDOG_CLK_ROOT, 85 }, + + { 0 } +}; + +static void +enablefracpll(u32int *reg, int ref_sel, int ref_freq, int freq) +{ + int divq, divr, ref, divfi, divff, pllout, error; + u32int cfg0, cfg1; + vlong v; + + cfg0 = reg[0]; + cfg1 = reg[1]; + + error = freq; + for(divq = 2; divq <= 64; divq += 2){ + for(divr = 1; divr <= 64; divr++){ + ref = ref_freq/divr; + if(ref < 10*Mhz || ref > 300*Mhz) + continue; + + ref *= 8; + divfi = ((vlong)freq*divq) / ref; + if(divfi < 1 || divfi > 32) + continue; + + v = ((vlong)freq*divq) - (vlong)ref*divfi; + divff = (v<<24) / ref; + if(divff < 1 || divff > (1<<24)) + continue; + + v = (vlong)ref*(vlong)divff; + pllout = (ref*divfi + (v>>24))/divq; + if(pllout < 30*Mhz || pllout > 2000*Mhz) + continue; + + if(pllout > freq) + continue; + + if(freq - pllout > error) + continue; + +// iprint("%p enablefracpll: freq=%d (actual %d)\n", PADDR(reg), freq, pllout); + + cfg0 = 1<<21 | ref_sel<<16 | 1<<15 | (divr-1)<<5 | (divq/2)-1; + cfg1 = divff<<7 | divfi-1; + + error = freq - pllout; + if(error == 0) + goto Found; + } + } + +Found: + /* skip if nothing has changed */ + if(((reg[0] ^ cfg0) & (1<<21 | 3<<16 | 1<<15 | 0x3F<<5 | 0x1F)) == 0 + && ((reg[1] ^ cfg1) & ~(1<<31)) == 0) + return; + + reg[0] |= 1<<14; /* bypass */ + +// iprint("%p cfg1=%.8ux\n", PADDR(reg), cfg1); + reg[1] = cfg1; + +// iprint("%p cfg0=%.8ux\n", PADDR(reg), cfg0); + reg[0] = cfg0 | (1<<14) | (1<<12); + + /* unbypass */ + reg[0] &= ~(1<<14); + +// iprint("%p wait for lock...", PADDR(reg)); + while((reg[0] & (1<<31)) == 0) + ; +// iprint("locked!\n"); + reg[0] &= ~(1<<12); +} + +static void +enablepll(int input) +{ + u32int old, val = 2; + + if(input < 0 || input > 38 || input_clk_freq[input] <= 0) + return; + + /* CCM_PLL_CTRL */ + old = regs[(0x800/4) + (16/4)*input] & 3; + if(old < val){ +// iprint("ccm: %s PLL_CTRL%d %.ux->%.ux\n", input_clk_name[input], input, old, val); + regs[(0x800/4) + (16/4)*input] = val; + } + + switch(input){ + case AUDIO_PLL1_CLK: + enablefracpll(&anatop[0x00/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case AUDIO_PLL2_CLK: + enablefracpll(&anatop[0x08/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case VIDEO_PLL1_CLK: + enablefracpll(&anatop[0x10/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case GPU_PLL_CLK: + enablefracpll(&anatop[0x18/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case VPU_PLL_CLK: + enablefracpll(&anatop[0x20/4], 0, 25*Mhz, input_clk_freq[input]); + break; + case ARM_PLL_CLK: + enablefracpll(&anatop[0x28/4], 0, 25*Mhz, input_clk_freq[input]); + break; + } +} + +static u32int +clkgate(Clock *gate, u32int val) +{ + u32int old; + + if(gate == nil || gate->ccgr == 0) + return 0; + + /* CCM_CCGR */ + old = regs[(0x4000/4) + (16/4)*gate->ccgr] & 3; + if(old != val){ +// if(gate->ccgr != 73) iprint("ccm: %s CCGR%d %.ux->%.ux\n", gate->name, gate->ccgr, old, val); + regs[(0x4000/4) + (16/4)*gate->ccgr] = val; + } + return old; +} + +static int +rootclkisipg(int root) +{ + switch(root){ + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + case MIPI_DSI_ESC_CLK_ROOT: + return 1; + } + return 0; +} + +static u32int +gettarget(int root) +{ + u32int val = regs[(0x8000/4) + (128/4)*root]; +// if(root != UART1_CLK_ROOT) iprint("ccm: %s TARGET_ROOT%d -> %.8ux\n", root_clk_name[root], root, val); + return val; +} + +static void +settarget(int root, Clock *gate, u32int val) +{ + if(gate != nil){ + for(; gate->name != nil; gate++){ + u32int old; + + if(gate->root != root) + continue; + + old = clkgate(gate, 0); + if(old == 0) + continue; + + /* skip restore when root is being disabled */ + if((val & (1<<28)) == 0) + continue; + + /* now change the root clock target */ + settarget(root, gate+1, val); + + /* restore gate */ + clkgate(gate, old); + return; + } + } + + if(rootclkisipg(root)) + val &= ~(1<<28); +// if(root != UART1_CLK_ROOT) iprint("ccm: %s TARGET_ROOT%d <- %.8ux\n", root_clk_name[root], root, val); + regs[(0x8000/4) + (128/4)*root] = val; +} + +static int +rootclkgetcfg(int root, int *input) +{ + u32int t = gettarget(root); + int freq = input_clk_freq[*input = root_clk_input_mux[root*8 + ((t >> 24)&7)]]; + int pre_podf = (t >> 16)&7; + int post_podf = (t >> 0)&0x3F; + + /* return negative frequency if disabled */ + if((t & (1<<28)) == 0) + freq = -freq; + + switch(root){ + case ARM_A53_CLK_ROOT: + case ARM_M4_CLK_ROOT: + case VPU_A53_CLK_ROOT: + case GPU_CORE_CLK_ROOT: + case GPU_SHADER_CLK_ROOT: + post_podf &= 7; + /* wet floor */ + case GPU_AXI_CLK_ROOT: + case GPU_AHB_CLK_ROOT: + case NOC_CLK_ROOT: + pre_podf = 0; + break; + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + post_podf &= 1; + case MIPI_DSI_ESC_CLK_ROOT: + freq = rootclkgetcfg(root-1, input); + /* wet floor */ + case AHB_CLK_ROOT: + case AUDIO_AHB_CLK_ROOT: + case MIPI_DSI_ESC_RX_CLK_ROOT: + pre_podf = 0; + break; + } + freq /= pre_podf+1; + freq /= post_podf+1; + + return freq; +} + +static void +rootclksetcfg(int root, int input, int freq) +{ + u32int t = gettarget(root); + + if(!rootclkisipg(root)){ + int mux; + + for(mux = 0; mux < 8; mux++){ + if(root_clk_input_mux[root*8 + mux] == input){ + t = (t & ~(7<<24)) | (mux << 24); + goto Muxok; + } + } + panic("rootclksetcfg: invalid input clock %d for TARGET_ROOT%d\n", input, root); +Muxok:; + } + /* disable by default */ + t &= ~(1 << 28); + + if(freq){ + int pre_mask, pre_podf, post_mask, post_podf; + int error, input_freq = input_clk_freq[input]; + + if(freq < 0) { + /* set dividers but keep disabled */ + freq = -freq; + } else { + /* set dividers and enable */ + t |= (1 << 28); + } + + pre_mask = 7; + post_mask = 0x3F; + + switch(root){ + case ARM_A53_CLK_ROOT: + case ARM_M4_CLK_ROOT: + case VPU_A53_CLK_ROOT: + case GPU_CORE_CLK_ROOT: + case GPU_SHADER_CLK_ROOT: + post_mask = 7; + /* wet floor */ + case GPU_AXI_CLK_ROOT: + case GPU_AHB_CLK_ROOT: + case NOC_CLK_ROOT: + pre_mask = 0; + break; + case IPG_CLK_ROOT: + case AUDIO_IPG_CLK_ROOT: + post_mask = 1; + case MIPI_DSI_ESC_CLK_ROOT: + input_freq = rootclkgetcfg(root-1, &input); + /* wet floor */ + case AHB_CLK_ROOT: + case AUDIO_AHB_CLK_ROOT: + case MIPI_DSI_ESC_RX_CLK_ROOT: + pre_mask = 0; + break; + } + if(input_freq < 0) input_freq = -input_freq; + + + error = freq; + for(pre_podf = 0; pre_podf <= pre_mask; pre_podf++){ + for(post_podf = 0; post_podf <= post_mask; post_podf++){ + int f = input_freq; + f /= pre_podf+1; + f /= post_podf+1; + if(f <= freq && (freq - f) < error){ + t = (t & ~(7<<16)) | (pre_podf << 16); + t = (t & ~0x3F) | post_podf; + error = freq - f; + if(error == 0) + break; + } + } + } + if(error >= freq) + panic("rootclksetcfg: frequency %d invalid for TARGET_ROOT%d\n", freq, root); + if(t & (1<<28)) + enablepll(input); + } + settarget(root, clocks, t); +} + +static int +lookinputclk(char *name) +{ + int i; + + for(i = 0; i < nelem(input_clk_name); i++){ + if(input_clk_name[i] != nil + && cistrcmp(name, input_clk_name[i]) == 0) + return i; + } + + return -1; +} + +static Clock* +lookmodclk(char *name) +{ + Clock *clk; + + for(clk = clocks; clk->name != nil; clk++){ + if(cistrcmp(name, clk->name) == 0) + return clk; + } + + return nil; +} + +static int +lookrootclk(char *name) +{ + Clock *clk; + int i; + + for(i = 0; i < nelem(root_clk_name); i++){ + if(root_clk_name[i] != nil + && cistrcmp(name, root_clk_name[i]) == 0) + return i; + } + + if((clk = lookmodclk(name)) != nil) + return clk->root; + + return -1; +} + +void +setclkgate(char *name, int on) +{ + clkgate(lookmodclk(name), on ? 3 : 0); +} + +void +setclkrate(char *name, char *source, int freq) +{ + int root, input; + + if((root = lookrootclk(name)) < 0) + panic("setclkrate: clock %s not defined", name); + if(source == nil) + rootclkgetcfg(root, &input); + else { + if((input = lookinputclk(source)) < 0) + panic("setclkrate: input clock %s not defined", source); + } + rootclksetcfg(root, input, freq); +} + +int +getclkrate(char *name) +{ + int root, input; + + if((root = lookrootclk(name)) >= 0) + return rootclkgetcfg(root, &input); + + if((input = lookinputclk(name)) > 0) + return input_clk_freq[input]; + + panic("getclkrate: clock %s not defined", name); + return -1; +} diff --git a/sys/src/9/imx8/etherimx.c b/sys/src/9/imx8/etherimx.c index 7a78c4c9d..893b04455 100644 --- a/sys/src/9/imx8/etherimx.c +++ b/sys/src/9/imx8/etherimx.c @@ -688,6 +688,16 @@ pnp(Ether *edev) edev->mbps = 1000; edev->maxmtu = Maxtu; + setclkgate("enet1.ipp_ind_mac0_txclk", 0); + setclkgate("sim_enet.mainclk", 0); + + setclkrate("enet1.ipg_clk", "system_pll1_div3", 266*Mhz); + setclkrate("enet1.ipp_ind_mac0_txclk", "system_pll2_div8", Moduleclk); + setclkrate("enet1.ipg_clk_time", "system_pll2_div10", 25*Mhz); + + setclkgate("enet1.ipp_ind_mac0_txclk", 1); + setclkgate("sim_enet.mainclk", 1); + if(reset(edev) < 0) return -1; diff --git a/sys/src/9/imx8/fns.h b/sys/src/9/imx8/fns.h index 146216073..31baa25c9 100644 --- a/sys/src/9/imx8/fns.h +++ b/sys/src/9/imx8/fns.h @@ -80,6 +80,7 @@ extern void meminit(void); extern void putasid(Proc*); extern void* ucalloc(usize); +extern void* fbmemalloc(usize); /* clock */ extern void clockinit(void); @@ -138,3 +139,11 @@ extern void writeconf(void); extern int isaconfig(char*, int, ISAConf*); extern void links(void); + +/* ccm */ +extern void setclkgate(char *name, int on); +extern void setclkrate(char *name, char *source, int freq); +extern int getclkrate(char *name); + +/* lcd */ +extern void lcdinit(void); diff --git a/sys/src/9/imx8/lcd.c b/sys/src/9/imx8/lcd.c new file mode 100644 index 000000000..d54d667b6 --- /dev/null +++ b/sys/src/9/imx8/lcd.c @@ -0,0 +1,949 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/i2c.h" + +#define Image IMAGE +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +extern Memimage *gscreen; + +/* pinmux registers */ +enum { + IOMUXC_CTL_PAD_SAI5_RXC = 0x144/4, /* for gpio3 20 */ + IOMUXC_CTL_PAD_SPDIF_RX = 0x1EC/4, /* for pwm2 */ + IOMUXC_CTL_PAD_GPIO1_IO10 = 0x50/4, /* for gpio1 10 */ + SION = 1<<4, + MUX_MODE = 7, + + IOMUXC_GPR_GPR13 = 0x10034/4, /* GPR13 for MIPI_MUX_SEL */ + MIPI_MUX_SEL = 1<<2, + MIPI_MUX_INV = 1<<3, +}; + +/* 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, +}; + +/* power gating controller registers */ +enum { + GPC_PGC_CPU_0_1_MAPPING = 0xEC/4, + GPC_PGC_PU_PGC_SW_PUP_REQ = 0xF8/4, + + GPC_A53_PU_PGC_PUP_STATUS0 = 0x1C4/4, + GPC_A53_PU_PGC_PUP_STATUS1 = 0x1C8/4, + GPC_A53_PU_PGC_PUP_STATUS2 = 0x1CC/4, + DISP_SW_PUP_REQ = 1<<10, + HDMI_SW_PUP_REQ = 1<<9, + MIPI_SW_PUP_REQ = 1<<0, +}; + +/* system reset controller registers */ +enum { + SRC_MIPIPHY_RCR = 0x28/4, + RCR_MIPI_DSI_PCLK_RESET_N = 1<<5, + RCR_MIPI_DSI_ESC_RESET_N = 1<<4, + RCR_MIPI_DSI_DPI_RESET_N = 1<<3, + RCR_MIPI_DSI_RESET_N = 1<<2, + RCR_MIPI_DSI_RESET_BYTE_N = 1<<1, + + SRC_DISP_RCR = 0x34/4, +}; + +/* pwm controller registers */ +enum { + Pwmsrcclk = 25*Mhz, + + PWMCR = 0x00/4, + CR_FWM_1 = 0<<26, + CR_FWM_2 = 1<<26, + CR_FWM_3 = 2<<26, + CR_FWM_4 = 3<<26, + + CR_STOPEN = 1<<25, + CR_DOZEN = 1<<24, + CR_WAITEN = 1<<23, + CR_DBGEN = 1<<22, + CR_BCTR = 1<<21, + CR_HCTR = 1<<20, + + CR_POUTC = 1<<18, + + CR_CLKSRC_OFF = 0<<16, + CR_CLKSRC_IPG = 1<<16, + CR_CLKSRC_HIGHFREQ = 2<<16, + CR_CLKSRC_32K = 3<<16, + + CR_PRESCALER_SHIFT = 4, + + CR_SWR = 1<<3, + + CR_REPEAT_1 = 0<<1, + CR_REPEAT_2 = 1<<1, + CR_REPEAT_4 = 2<<1, + CR_REPEAT_8 = 3<<1, + + CR_EN = 1<<0, + + PWMSR = 0x04/4, + PWMIR = 0x08/4, + PWMSAR = 0x0C/4, + SAR_MASK = 0xFFFF, + PWMPR = 0x10/4, + PR_MASK = 0xFFFF, + PWMCNR = 0x14/4, + CNR_MASK = 0xFFFF, +}; + +/* dphy registers */ +enum { + DPHY_PD_PHY = 0x0/4, + DPHY_M_PRG_HS_PREPARE = 0x4/4, + DPHY_MC_PRG_HS_PREPARE = 0x8/4, + DPHY_M_PRG_HS_ZERO = 0xc/4, + DPHY_MC_PRG_HS_ZERO = 0x10/4, + DPHY_M_PRG_HS_TRAIL = 0x14/4, + DPHY_MC_PRG_HS_TRAIL = 0x18/4, + DPHY_PD_PLL = 0x1c/4, + DPHY_TST = 0x20/4, + DPHY_CN = 0x24/4, + DPHY_CM = 0x28/4, + DPHY_CO = 0x2c/4, + DPHY_LOCK = 0x30/4, + DPHY_LOCK_BYP = 0x34/4, + DPHY_RTERM_SEL = 0x38/4, + DPHY_AUTO_PD_EN = 0x3c/4, + DPHY_RXLPRP = 0x40/4, + DPHY_RXCDR = 0x44/4, + DPHY_RXHS_SETTLE = 0x48/4, /* undocumented */ +}; + +/* dsi-host registers */ +enum { + DSI_HOST_CFG_NUM_LANES = 0x0/4, + DSI_HOST_CFG_NONCONTINUOUS_CLK = 0x4/4, + DSI_HOST_CFG_AUTOINSERT_EOTP = 0x14/4, + DSI_HOST_CFG_T_PRE = 0x8/4, + DSI_HOST_CFG_T_POST = 0xc/4, + DSI_HOST_CFG_TX_GAP = 0x10/4, + DSI_HOST_CFG_EXTRA_CMDS_AFTER_EOTP = 0x18/4, + DSI_HOST_CFG_HTX_TO_COUNT = 0x1c/4, + DSI_HOST_CFG_LRX_H_TO_COUNT = 0x20/4, + DSI_HOST_CFG_BTA_H_TO_COUNT = 0x24/4, + DSI_HOST_CFG_TWAKEUP = 0x28/4, + + DSI_HOST_CFG_DPI_INTERFACE_COLOR_CODING = 0x208/4, + DSI_HOST_CFG_DPI_PIXEL_FORMAT = 0x20c/4, + DSI_HOST_CFG_DPI_VSYNC_POLARITY = 0x210/4, + DSI_HOST_CFG_DPI_HSYNC_POLARITY = 0x214/4, + DSI_HOST_CFG_DPI_VIDEO_MODE = 0x218/4, + DSI_HOST_CFG_DPI_PIXEL_FIFO_SEND_LEVEL = 0x204/4, + DSI_HOST_CFG_DPI_HFP = 0x21c/4, + DSI_HOST_CFG_DPI_HBP = 0x220/4, + DSI_HOST_CFG_DPI_HSA = 0x224/4, + DSI_HOST_CFG_DPI_ENA_BLE_MULT_PKTS = 0x228/4, + DSI_HOST_CFG_DPI_BLLP_MODE = 0x234/4, + DSI_HOST_CFG_DPI_USE_NULL_PKT_BLLP = 0x238/4, + DSI_HOST_CFG_DPI_VC = 0x240/4, + DSI_HOST_CFG_DPI_PIXEL_PAYLOAD_SIZE = 0x200/4, + DSI_HOST_CFG_DPI_VACTIVE = 0x23c/4, + DSI_HOST_CFG_DPI_VBP = 0x22c/4, + DSI_HOST_CFG_DPI_VFP = 0x230/4, +}; + +/* lcdif registers */ +enum { + LCDIF_CTRL = 0x00/4, + LCDIF_CTRL_SET = 0x04/4, + LCDIF_CTRL_CLR = 0x08/4, + LCDIF_CTRL_TOG = 0x0C/4, + CTRL_SFTRST = 1<<31, + CTRL_CLKGATE = 1<<30, + CTRL_YCBCR422_INPUT = 1<<29, + CTRL_READ_WEITEB = 1<<28, + CTRL_WAIT_FOR_VSYNC_EDGE = 1<<27, + CTRL_DATA_SHIFT_DIR = 1<<26, + CTRL_SHIFT_NUM_BITS = 0x1F<<21, + CTRL_DVI_MODE = 1<<20, + CTRL_BYPASS_COUNT = 1<<19, + CTRL_VSYNC_MODE = 1<<18, + CTRL_DOTCLK_MODE = 1<<17, + CTRL_DATA_SELECT = 1<<16, + + CTRL_INPUT_DATA_NO_SWAP = 0<<14, + CTRL_INPUT_DATA_LITTLE_ENDIAN = 0<<14, + CTRL_INPUT_DATA_BIG_ENDIAB = 1<<14, + CTRL_INPUT_DATA_SWAP_ALL_BYTES = 1<<14, + CTRL_INPUT_DATA_HWD_SWAP = 2<<14, + CTRL_INPUT_DATA_HWD_BYTE_SWAP = 3<<14, + + CTRL_CSC_DATA_NO_SWAP = 0<<12, + CTRL_CSC_DATA_LITTLE_ENDIAN = 0<<12, + CTRL_CSC_DATA_BIG_ENDIAB = 1<<12, + CTRL_CSC_DATA_SWAP_ALL_BYTES = 1<<12, + CTRL_CSC_DATA_HWD_SWAP = 2<<12, + CTRL_CSC_DATA_HWD_BYTE_SWAP = 3<<12, + + CTRL_LCD_DATABUS_WIDTH_16_BIT = 0<<10, + CTRL_LCD_DATABUS_WIDTH_8_BIT = 1<<10, + CTRL_LCD_DATABUS_WIDTH_18_BIT = 2<<10, + CTRL_LCD_DATABUS_WIDTH_24_BIT = 3<<10, + + CTRL_WORD_LENGTH_16_BIT = 0<<8, + CTRL_WORD_LENGTH_8_BIT = 1<<8, + CTRL_WORD_LENGTH_18_BIT = 2<<8, + CTRL_WORD_LENGTH_24_BIT = 3<<8, + + CTRL_RGB_TO_YCBCR422_CSC = 1<<7, + + CTRL_MASTER = 1<<5, + + CTRL_DATA_FORMAT_16_BIT = 1<<3, + CTRL_DATA_FORMAT_18_BIT = 1<<2, + CTRL_DATA_FORMAT_24_BIT = 1<<1, + + CTRL_RUN = 1<<0, + + LCDIF_CTRL1 = 0x10/4, + LCDIF_CTRL1_SET = 0x14/4, + LCDIF_CTRL1_CLR = 0x18/4, + LCDIF_CTRL1_TOG = 0x1C/4, + CTRL1_COMBINE_MPU_WR_STRB = 1<<27, + CTRL1_BM_ERROR_IRQ_EN = 1<<26, + CTRL1_BM_ERROR_IRQ = 1<<25, + CTRL1_RECOVER_ON_UNDERFLOW = 1<<24, + + CTRL1_INTERLACE_FIELDS = 1<<23, + CTRL1_START_INTERLACE_FROM_SECOND_FIELD = 1<<22, + + CTRL1_FIFO_CLEAR = 1<<21, + CTRL1_IRQ_ON_ALTERNATE_FIELDS = 1<<20, + + CTRL1_BYTE_PACKING_FORMAT = 0xF<<16, + + CTRL1_OVERFLOW_IRQ_EN = 1<<15, + CTRL1_UNDERFLOW_IRQ_EN = 1<<14, + CTRL1_CUR_FRAME_DONE_IRQ_EN = 1<<13, + CTRL1_VSYNC_EDGE_IRQ_EN = 1<<12, + CTRL1_OVERFLOW_IRQ = 1<<11, + CTRL1_UNDERFLOW_IRQ = 1<<10, + CTRL1_CUR_FRAME_DONE_IRQ = 1<<9, + CTRL1_VSYNC_EDGE_IRQ = 1<<8, + + CTRL1_BUSY_ENABLE = 1<<2, + CTRL1_MODE86 = 1<<1, + CTRL1_RESET = 1<<0, + + LCDIF_CTRL2 = 0x20/4, + LCDIF_CTRL2_SET = 0x24/4, + LCDIF_CTRL2_CLR = 0x28/4, + LCDIF_CTRL2_TOG = 0x2C/4, + CTRL2_OUTSTANDING_REQS_REQ_1 = 0<<21, + CTRL2_OUTSTANDING_REQS_REQ_2 = 1<<21, + CTRL2_OUTSTANDING_REQS_REQ_4 = 2<<21, + CTRL2_OUTSTANDING_REQS_REQ_8 = 3<<21, + CTRL2_OUTSTANDING_REQS_REQ_16 = 4<<21, + + CTRL2_BURST_LEN_8 = 1<<20, + + CTRL2_ODD_LINE_PATTERN_RGB = 0<<16, + CTRL2_ODD_LINE_PATTERN_RBG = 1<<16, + CTRL2_ODD_LINE_PATTERN_GBR = 2<<16, + CTRL2_ODD_LINE_PATTERN_GRB = 3<<16, + CTRL2_ODD_LINE_PATTERN_BRG = 4<<16, + CTRL2_ODD_LINE_PATTERN_BGR = 5<<16, + + CTRL2_EVEN_LINE_PATTERN_RGB = 0<<12, + CTRL2_EVEN_LINE_PATTERN_RBG = 1<<12, + CTRL2_EVEN_LINE_PATTERN_GBR = 2<<12, + CTRL2_EVEN_LINE_PATTERN_GRB = 3<<12, + CTRL2_EVEN_LINE_PATTERN_BRG = 4<<12, + CTRL2_EVEN_LINE_PATTERN_BGR = 5<<12, + + CTRL2_READ_PACK_DIR = 1<<10, + + CTRL2_READ_MODE_OUTPUT_IN_RGB_FORMAT = 1<<9, + CTRL2_READ_MODE_6_BIT_INPUT = 1<<8, + CTRL2_READ_MODE_NUM_PACKED_SUBWORDS = 7<<4, + CTRL2_INITIAL_DUMMY_READS = 7<<1, + + LCDIF_TRANSFER_COUNT= 0x30/4, + TRANSFER_COUNT_V_COUNT = 0xFFFF<<16, + TRANSFER_COUNT_H_COUNT = 0xFFFF, + + LCDIF_CUR_BUF = 0x40/4, + LCDIF_NEXT_BUF = 0x50/4, + + LCDIF_TIMING = 0x60/4, + TIMING_CMD_HOLD = 0xFF<<24, + TIMING_CMD_SETUP = 0xFF<<16, + TIMING_DATA_HOLD = 0xFF<<8, + TIMING_DATA_SETUP = 0xFF<<0, + + LCDIF_VDCTRL0 = 0x70/4, + VDCTRL0_VSYNC_OEB = 1<<29, + VDCTRL0_ENABLE_PRESENT = 1<<28, + + VDCTRL0_VSYNC_POL = 1<<27, + VDCTRL0_HSYNC_POL = 1<<26, + VDCTRL0_DOTCLK_POL = 1<<25, + VDCTRL0_ENABLE_POL = 1<<24, + + VDCTRL0_VSYNC_PERIOD_UNIT = 1<<21, + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT = 1<<20, + VDCTRL0_HALF_LINE = 1<<19, + VDCTRL0_HALF_LINE_MODE = 1<<18, + + VDCTRL0_VSYNC_PULSE_WIDTH = 0x3FFFF, + + LCDIF_VDCTRL1 = 0x80/4, + VDCTRL1_VSYNC_PERIOD = 0xFFFFFFFF, + + LCDIF_VDCTRL2 = 0x90/4, + VDCTRL2_HSYNC_PERIOD = 0x3FFFF, + VDCTRL2_HSYNC_PULSE_WIDTH = 0x3FFF<<18, + + LCDIF_VDCTRL3 = 0xA0/4, + VDCTRL3_VERTICAL_WAIT_CNT = 0xFFFF, + VDCTRL3_HORIZONTAL_WAIT_CNT = 0xFFF<<16, + VDCTRL3_VSYNC_ONLY = 1<<28, + VDCTRL3_MUX_SYNC_SIGNALS = 1<<29, + + LCDIF_VDCTRL4 = 0xB0/4, + VDCTRL4_DOTCLK_H_VALID_DATA_CNT = 0x3FFFF, + VDCTRL4_SYNC_SIGNALS_ON = 1<<18, + + VDCTRL4_DOTCLK_DLY_2NS = 0<<29, + VDCTRL4_DOTCLK_DLY_4NS = 1<<29, + VDCTRL4_DOTCLK_DLY_6NS = 2<<29, + VDCTRL4_DOTCLK_DLY_8NS = 3<<29, + + LCDIF_DATA = 0x180/4, + + LCDIF_STAT = 0x1B0/4, + + LCDIF_AS_CTRL = 0x210/4, +}; + +struct video_mode { + int pixclk; + int hactive; + int vactive; + int hblank; + int vblank; + int hso; + int vso; + int hspw; + int vspw; + + char vsync_pol; + char hsync_pol; +}; + +struct dsi_cfg { + int lanes; + + int ref_clk; + int hs_clk; + int ui_ps; + + int byte_clk; + int byte_t_ps; + + int tx_esc_clk; + int tx_esc_t_ps; + + int rx_esc_clk; + + int clk_pre_ps; + int clk_prepare_ps; + int clk_zero_ps; + + int hs_prepare_ps; + int hs_zero_ps; + int hs_trail_ps; + int hs_exit_ps; + + int lpx_ps; + + vlong wakeup_ps; +}; + +/* base addresses, VIRTIO is at 0x30000000 physical */ + +static u32int *iomuxc = (u32int*)(VIRTIO + 0x330000); + +static u32int *gpio1 = (u32int*)(VIRTIO + 0x200000); +static u32int *gpio3 = (u32int*)(VIRTIO + 0x220000); + +static u32int *pwm2 = (u32int*)(VIRTIO + 0x670000); + +static u32int *resetc= (u32int*)(VIRTIO + 0x390000); +static u32int *gpc = (u32int*)(VIRTIO + 0x3A0000); + +static u32int *dsi = (u32int*)(VIRTIO + 0xA00000); +static u32int *dphy = (u32int*)(VIRTIO + 0xA00300); + +static u32int *lcdif = (u32int*)(VIRTIO + 0x320000); + +/* shift and mask */ +static u32int +sm(u32int v, u32int m) +{ + int s; + + if(m == 0) + return 0; + + s = 0; + while((m & 1) == 0){ + m >>= 1; + s++; + } + + return (v & m) << s; +} + +static u32int +rr(u32int *base, int reg) +{ + u32int val = base[reg]; +// iprint("%#p+%#.4x -> %#.8ux\n", PADDR(base), reg*4, val); + return val; +} +static void +wr(u32int *base, int reg, u32int val) +{ +// iprint("%#p+%#.4x <- %#.8ux\n", PADDR(base), reg*4, val); + base[reg] = val; +} +static void +mr(u32int *base, int reg, u32int val, u32int mask) +{ + wr(base, reg, (rr(base, reg) & ~mask) | (val & mask)); +} + +static void +dsiparams(struct dsi_cfg *cfg, int lanes, int hs_clk, int ref_clk, int tx_esc_clk, int rx_esc_clk) +{ + cfg->lanes = lanes; + cfg->ref_clk = ref_clk; + + cfg->hs_clk = hs_clk; + cfg->ui_ps = (1000000000000LL + (cfg->hs_clk-1)) / cfg->hs_clk; + + cfg->byte_clk = cfg->hs_clk / 8; + cfg->byte_t_ps = cfg->ui_ps * 8; + + cfg->tx_esc_clk = tx_esc_clk; + cfg->tx_esc_t_ps = (1000000000000LL + (cfg->tx_esc_clk-1)) / cfg->tx_esc_clk; + + cfg->rx_esc_clk = rx_esc_clk; + + /* min 8*ui */ + cfg->clk_pre_ps = 8*cfg->ui_ps; + + /* min 38ns, max 95ns */ + cfg->clk_prepare_ps = 38*1000; + + /* clk_prepare + clk_zero >= 300ns */ + cfg->clk_zero_ps = 300*1000 - cfg->clk_prepare_ps; + + /* min 40ns + 4*ui, max 85ns + 6*ui */ + cfg->hs_prepare_ps = 40*1000 + 4*cfg->ui_ps; + + /* hs_prepae + hs_zero >= 145ns + 10*ui */ + cfg->hs_zero_ps = (145*1000 + 10*cfg->ui_ps) - cfg->hs_prepare_ps; + + /* min max(n*8*ui, 60ns + n*4*ui); n=1 */ + cfg->hs_trail_ps = 60*1000 + 1*4*cfg->ui_ps; + if(cfg->hs_trail_ps < 1*8*cfg->ui_ps) + cfg->hs_trail_ps = 1*8*cfg->ui_ps; + + /* min 100ns */ + cfg->hs_exit_ps = 100*1000; + + /* min 50ns */ + cfg->lpx_ps = 50*1000; + + /* min 1ms */ + cfg->wakeup_ps = 1000000000000LL; +} + +static void +lcdifinit(struct video_mode *mode) +{ + wr(lcdif, LCDIF_CTRL_CLR, CTRL_SFTRST); + while(rr(lcdif, LCDIF_CTRL) & CTRL_SFTRST) + ; + wr(lcdif, LCDIF_CTRL_CLR, CTRL_CLKGATE); + while(rr(lcdif, LCDIF_CTRL) & (CTRL_SFTRST|CTRL_CLKGATE)) + ; + + wr(lcdif, LCDIF_CTRL1_SET, CTRL1_FIFO_CLEAR); + wr(lcdif, LCDIF_AS_CTRL, 0); + + wr(lcdif, LCDIF_CTRL1, sm(7, CTRL1_BYTE_PACKING_FORMAT)); + + wr(lcdif, LCDIF_CTRL, + CTRL_BYPASS_COUNT | + CTRL_MASTER | + CTRL_LCD_DATABUS_WIDTH_24_BIT | + CTRL_WORD_LENGTH_24_BIT); + + wr(lcdif, LCDIF_TRANSFER_COUNT, + sm(mode->vactive, TRANSFER_COUNT_V_COUNT) | + sm(mode->hactive, TRANSFER_COUNT_H_COUNT)); + + wr(lcdif, LCDIF_VDCTRL0, + VDCTRL0_ENABLE_PRESENT | + VDCTRL0_VSYNC_POL | VDCTRL0_HSYNC_POL | + VDCTRL0_VSYNC_PERIOD_UNIT | + VDCTRL0_VSYNC_PULSE_WIDTH_UNIT | + sm(mode->vspw, VDCTRL0_VSYNC_PULSE_WIDTH)); + + wr(lcdif, LCDIF_VDCTRL1, + sm(mode->vactive + mode->vblank, VDCTRL1_VSYNC_PERIOD)); + + wr(lcdif, LCDIF_VDCTRL2, + sm(mode->hactive + mode->hblank, VDCTRL2_HSYNC_PERIOD) | + sm(mode->hspw, VDCTRL2_HSYNC_PULSE_WIDTH)); + + wr(lcdif, LCDIF_VDCTRL3, + sm(mode->vblank - mode->vso, VDCTRL3_VERTICAL_WAIT_CNT) | + sm(mode->hblank - mode->hso, VDCTRL3_HORIZONTAL_WAIT_CNT)); + + wr(lcdif, LCDIF_VDCTRL4, + sm(mode->hactive, VDCTRL4_DOTCLK_H_VALID_DATA_CNT)); + + wr(lcdif, LCDIF_CUR_BUF, PADDR(gscreen->data->bdata)); + wr(lcdif, LCDIF_NEXT_BUF, PADDR(gscreen->data->bdata)); + + wr(lcdif, LCDIF_CTRL_SET, CTRL_DOTCLK_MODE); + + mr(lcdif, LCDIF_VDCTRL4, VDCTRL4_SYNC_SIGNALS_ON, VDCTRL4_SYNC_SIGNALS_ON); + + wr(lcdif, LCDIF_CTRL_SET, CTRL_RUN); +} + +static void +bridgeinit(I2Cdev *dev, struct video_mode *mode, struct dsi_cfg *cfg) +{ + int n; + + // clock derived from dsi clock + switch(cfg->hs_clk/2000000){ + case 384: + default: n = 1 << 1; break; + case 416: n = 2 << 1; break; + case 468: n = 0 << 1; break; + case 486: n = 3 << 1; break; + case 461: n = 4 << 1; break; + } + i2cwritebyte(dev, 0x0a, n); + + // single channel A + n = 1<<5 | (cfg->lanes-4)<<3 | 3<<1; + i2cwritebyte(dev, 0x10, n); + + // Enhanced framing and ASSR + i2cwritebyte(dev, 0x5a, 0x05); + + // 2 DP lanes w/o SSC + i2cwritebyte(dev, 0x93, 0x20); + + // 2.7Gbps DP data rate + i2cwritebyte(dev, 0x94, 0x80); + + // Enable PLL and confirm PLL is locked + i2cwritebyte(dev, 0x0d, 0x01); + + // wait for PLL to lock + while((i2creadbyte(dev, 0x0a) & 0x80) == 0) + ; + + // Enable ASSR on display + i2cwritebyte(dev, 0x64, 0x01); + i2cwritebyte(dev, 0x75, 0x01); + i2cwritebyte(dev, 0x76, 0x0a); + i2cwritebyte(dev, 0x77, 0x01); + i2cwritebyte(dev, 0x78, 0x81); + + // Train link and confirm trained + i2cwritebyte(dev, 0x96, 0x0a); + while(i2creadbyte(dev, 0x96) != 1) + ; + + // video timings + i2cwritebyte(dev, 0x20, mode->hactive & 0xFF); + i2cwritebyte(dev, 0x21, mode->hactive >> 8); + i2cwritebyte(dev, 0x24, mode->vactive & 0xFF); + i2cwritebyte(dev, 0x25, mode->vactive >> 8); + i2cwritebyte(dev, 0x2c, mode->hspw); + i2cwritebyte(dev, 0x2d, mode->hspw>>8 | (mode->hsync_pol=='-')<<7); + i2cwritebyte(dev, 0x30, mode->vspw); + i2cwritebyte(dev, 0x31, mode->vspw>>8 | (mode->vsync_pol=='-')<<7); + i2cwritebyte(dev, 0x34, mode->hblank - mode->hspw - mode->hso); + i2cwritebyte(dev, 0x36, mode->vblank - mode->vspw - mode->vso); + i2cwritebyte(dev, 0x38, mode->hso); + i2cwritebyte(dev, 0x3a, mode->vso); + + // Enable video stream, ASSR, enhanced framing + i2cwritebyte(dev, 0x5a, 0x0d); +} + +static char* +parseedid128(struct video_mode *mode, uchar edid[128]) +{ + static uchar magic[8] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; + uchar *p, sum; + int i; + + if(memcmp(edid, magic, 8) != 0) + return "bad edid magic"; + + sum = 0; + for(i=0; i<128; i++) + sum += edid[i]; + if(sum != 0) + return "bad edid checksum"; + + /* + * Detailed Timings + */ + p = edid+8+10+2+5+10+3+16; + for(i=0; i<4; i++, p+=18){ + if((p[0]|p[1])==0) + continue; + + memset(mode, 0, sizeof(*mode)); + + mode->pixclk = ((p[1]<<8) | p[0]) * 10000; + + mode->hactive = ((p[4] & 0xF0)<<4) | p[2]; /* horizontal active */ + mode->hblank = ((p[4] & 0x0F)<<8) | p[3]; /* horizontal blanking */ + mode->vactive = ((p[7] & 0xF0)<<4) | p[5]; /* vertical active */ + mode->vblank = ((p[7] & 0x0F)<<8) | p[6]; /* vertical blanking */ + mode->hso = ((p[11] & 0xC0)<<2) | p[8]; /* horizontal sync offset */ + mode->hspw = ((p[11] & 0x30)<<4) | p[9]; /* horizontal sync pulse width */ + mode->vso = ((p[11] & 0x0C)<<2) | ((p[10] & 0xF0)>>4); /* vertical sync offset */ + mode->vspw = ((p[11] & 0x03)<<4) | (p[10] & 0x0F); /* vertical sync pulse width */ + + switch((p[17] & 0x18)>>3) { + case 3: /* digital separate sync signal; the norm */ + mode->vsync_pol = (p[17] & 0x04) ? '+' : '-'; + mode->hsync_pol = (p[17] & 0x02) ? '+' : '-'; + break; + } + + return nil; + } + + return "no edid timings available"; +} + +static char* +getmode(I2Cdev *dev, struct video_mode *mode) +{ + static uchar edid[128]; + static I2Cdev aux; + + aux.bus = dev->bus; + aux.addr = 0x50; + aux.subaddr = 1; + aux.size = sizeof(edid); + + /* enable passthru mode for address 0x50 (EDID) */ + i2cwritebyte(dev, 0x60, aux.addr<<1 | 1); + addi2cdev(&aux); + + if(i2crecv(&aux, edid, sizeof(edid), 0) != sizeof(edid)) + return "i2crecv failed to get edid bytes"; + + return parseedid128(mode, edid); +} + +static void +dphyinit(struct dsi_cfg *cfg) +{ + int n; + + /* powerdown */ + wr(dphy, DPHY_PD_PLL, 1); + wr(dphy, DPHY_PD_PHY, 1); + + /* magic */ + wr(dphy, DPHY_LOCK_BYP, 0); + wr(dphy, DPHY_RTERM_SEL, 1); + wr(dphy, DPHY_AUTO_PD_EN, 0); + wr(dphy, DPHY_RXLPRP, 2); + wr(dphy, DPHY_RXCDR, 2); + wr(dphy, DPHY_TST, 0x25); + + /* hs timings */ + n = (2*cfg->hs_prepare_ps - cfg->tx_esc_t_ps) / cfg->tx_esc_t_ps; + if(n < 0) + n = 0; + else if(n > 3) + n = 3; + wr(dphy, DPHY_M_PRG_HS_PREPARE, n); + + n = (2*cfg->clk_prepare_ps - cfg->tx_esc_t_ps) / cfg->tx_esc_t_ps; + if(n < 0) + n = 0; + else if(n > 1) + n = 1; + wr(dphy, DPHY_MC_PRG_HS_PREPARE, n); + + n = ((cfg->hs_zero_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps) - 6; + if(n < 1) + n = 1; + wr(dphy, DPHY_M_PRG_HS_ZERO, n); + + n = ((cfg->clk_zero_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps) - 3; + if(n < 1) + n = 1; + wr(dphy, DPHY_MC_PRG_HS_ZERO, n); + + n = (cfg->hs_trail_ps + (cfg->byte_t_ps-1)) / cfg->byte_t_ps; + if(n < 1) + n = 1; + else if(n > 15) + n = 15; + wr(dphy, DPHY_M_PRG_HS_TRAIL, n); + wr(dphy, DPHY_MC_PRG_HS_TRAIL, n); + + if(cfg->hs_clk < 80*Mhz) + n = 0xD; + else if(cfg->hs_clk < 90*Mhz) + n = 0xC; + else if(cfg->hs_clk < 125*Mhz) + n = 0xB; + else if(cfg->hs_clk < 150*Mhz) + n = 0xA; + else if(cfg->hs_clk < 225*Mhz) + n = 0x9; + else if(cfg->hs_clk < 500*Mhz) + n = 0x8; + else + n = 0x7; + wr(dphy, DPHY_RXHS_SETTLE, n); + + /* hs_clk = ref_clk * (CM / (CN*CO)); just set CN=CO=1 */ + n = (cfg->hs_clk + cfg->ref_clk-1) / cfg->ref_clk; + + /* strange encoding for CM */ + if(n < 32) + n = 0xE0 | (n - 16); + else if(n < 64) + n = 0xC0 | (n - 32); + else if(n < 128) + n = 0x80 | (n - 64); + else + n = n - 128; + wr(dphy, DPHY_CM, n); + + wr(dphy, DPHY_CN, 0x1F); /* CN==1 */ + wr(dphy, DPHY_CO, 0x00); /* CO==1 */ +} + +static void +dphypowerup(void) +{ + wr(dphy, DPHY_PD_PLL, 0); + while((rr(dphy, DPHY_LOCK) & 1) == 0) + ; + wr(dphy, DPHY_PD_PHY, 0); +} + +static void +dsiinit(struct dsi_cfg *cfg) +{ + int n; + + wr(dsi, DSI_HOST_CFG_NUM_LANES, cfg->lanes-1); + + wr(dsi, DSI_HOST_CFG_NONCONTINUOUS_CLK, 0x0); + wr(dsi, DSI_HOST_CFG_AUTOINSERT_EOTP, 0x0); + + n = (cfg->clk_pre_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_T_PRE, n); + + n = (cfg->clk_pre_ps + cfg->lpx_ps + cfg->clk_prepare_ps + cfg->clk_zero_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_T_POST, n); + + n = (cfg->hs_exit_ps + cfg->byte_t_ps-1) / cfg->byte_t_ps; + wr(dsi, DSI_HOST_CFG_TX_GAP, n); + + wr(dsi, DSI_HOST_CFG_EXTRA_CMDS_AFTER_EOTP, 0x1); + + wr(dsi, DSI_HOST_CFG_HTX_TO_COUNT, 0x0); + wr(dsi, DSI_HOST_CFG_LRX_H_TO_COUNT, 0x0); + wr(dsi, DSI_HOST_CFG_BTA_H_TO_COUNT, 0x0); + + n = (cfg->wakeup_ps + cfg->tx_esc_t_ps-1) / cfg->tx_esc_t_ps; + wr(dsi, DSI_HOST_CFG_TWAKEUP, n); +} + +static void +dpiinit(struct video_mode *mode) +{ + wr(dsi, DSI_HOST_CFG_DPI_INTERFACE_COLOR_CODING, 0x5); // 24-bit + + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_FORMAT, 0x3); // 24-bit + + /* this seems wrong */ + wr(dsi, DSI_HOST_CFG_DPI_VSYNC_POLARITY, 0); + wr(dsi, DSI_HOST_CFG_DPI_HSYNC_POLARITY, 0); + + wr(dsi, DSI_HOST_CFG_DPI_VIDEO_MODE, 0x1); // non-burst mode with sync events + + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_FIFO_SEND_LEVEL, mode->hactive); + + wr(dsi, DSI_HOST_CFG_DPI_HFP, mode->hso); + wr(dsi, DSI_HOST_CFG_DPI_HBP, mode->hblank - mode->hspw - mode->hso); + wr(dsi, DSI_HOST_CFG_DPI_HSA, mode->hspw); + + wr(dsi, DSI_HOST_CFG_DPI_ENA_BLE_MULT_PKTS, 0x0); + + wr(dsi, DSI_HOST_CFG_DPI_BLLP_MODE, 0x1); + + wr(dsi, DSI_HOST_CFG_DPI_USE_NULL_PKT_BLLP, 0x0); + + wr(dsi, DSI_HOST_CFG_DPI_VC, 0x0); + wr(dsi, DSI_HOST_CFG_DPI_PIXEL_PAYLOAD_SIZE, mode->hactive); + wr(dsi, DSI_HOST_CFG_DPI_VACTIVE, mode->vactive - 1); + wr(dsi, DSI_HOST_CFG_DPI_VBP, mode->vblank - mode->vspw - mode->vso); + wr(dsi, DSI_HOST_CFG_DPI_VFP, mode->vso); +} + +void +lcdinit(void) +{ + struct dsi_cfg dsi_cfg; + struct video_mode mode; + I2Cdev *bridge; + char *err; + + /* gpio3 20 for sn65dsi86 bridge */ + mr(iomuxc, IOMUXC_CTL_PAD_SAI5_RXC, 5, MUX_MODE); + /* gpio1 10 pad for panel */ + mr(iomuxc, IOMUXC_CTL_PAD_GPIO1_IO10, 0, MUX_MODE); + /* pwm2 pad */ + mr(iomuxc, IOMUXC_CTL_PAD_SPDIF_RX, 1, MUX_MODE); + + /* lcdif to dpi=0, dcss=1 */ + mr(iomuxc, IOMUXC_GPR_GPR13, 0, MIPI_MUX_SEL); + + setclkgate("gpio1.ipg_clk_s", 1); + setclkgate("gpio3.ipg_clk_s", 1); + + setclkrate("pwm2.ipg_clk_high_freq", "osc_25m_ref_clk", Pwmsrcclk); + setclkgate("pwm2.ipg_clk_high_freq", 1); + + mr(gpio1, GPIO_GDIR, 1<<10, 1<<10); /* gpio1 10 output */ + mr(gpio1, GPIO_DR, 0<<10, 1<<10); /* gpio1 10 low: panel off */ + + wr(pwm2, PWMIR, 0); + wr(pwm2, PWMCR, CR_STOPEN | CR_DOZEN | CR_WAITEN | CR_DBGEN | CR_CLKSRC_HIGHFREQ | 0<<CR_PRESCALER_SHIFT); + wr(pwm2, PWMSAR, Pwmsrcclk/150000); + wr(pwm2, PWMPR, (Pwmsrcclk/100000)-2); + mr(pwm2, PWMCR, CR_EN, CR_EN); + + mr(gpio1, GPIO_DR, 1<<10, 1<<10); /* gpio1 10 high: panel on */ + + mr(gpio3, GPIO_GDIR, 1<<20, 1<<20); /* gpio3 20 output */ + mr(gpio3, GPIO_DR, 1<<20, 1<<20); /* gpio3 20 high: bridge on */ + + bridge = i2cdev(i2cbus("i2c4"), 0x2C); + if(bridge == nil) + return; + bridge->subaddr = 1; + + /* power on mipi dsi */ + wr(gpc, GPC_PGC_CPU_0_1_MAPPING, 0x0000FFFF); + mr(gpc, GPC_PGC_PU_PGC_SW_PUP_REQ, MIPI_SW_PUP_REQ, MIPI_SW_PUP_REQ); + while(rr(gpc, GPC_PGC_PU_PGC_SW_PUP_REQ) & MIPI_SW_PUP_REQ) + ; + wr(gpc, GPC_PGC_CPU_0_1_MAPPING, 0); + + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_PCLK_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_ESC_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_RESET_BYTE_N); + mr(resetc, SRC_MIPIPHY_RCR, 0, RCR_MIPI_DSI_DPI_RESET_N); + + setclkgate("sim_display.mainclk", 0); + setclkgate("disp.axi_clk", 0); + setclkrate("disp.axi_clk", "system_pll1_clk", 800*Mhz); + setclkrate("disp.rtrm_clk", "system_pll1_clk", 400*Mhz); + setclkgate("disp.axi_clk", 1); + setclkgate("sim_display.mainclk", 1); + + setclkrate("mipi.core", "system_pll1_div3", 266*Mhz); + setclkrate("mipi.CLKREF", "system_pll2_clk", 25*Mhz); + setclkrate("mipi.RxClkEsc", "system_pll1_clk", 80*Mhz); + setclkrate("mipi.TxClkEsc", nil, 20*Mhz); + + /* dsi parameters are fixed for the bridge */ + dsiparams(&dsi_cfg, 4, 2*486*Mhz, + getclkrate("mipi.CLKREF"), + getclkrate("mipi.TxClkEsc"), + getclkrate("mipi.RxClkEsc")); + + /* release dphy reset */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_PCLK_RESET_N, RCR_MIPI_DSI_PCLK_RESET_N); + + dphyinit(&dsi_cfg); + dsiinit(&dsi_cfg); + dphypowerup(); + + /* release mipi clock resets (generated by the dphy) */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_ESC_RESET_N, RCR_MIPI_DSI_ESC_RESET_N); + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_RESET_BYTE_N, RCR_MIPI_DSI_RESET_BYTE_N); + + /* + * get mode information from EDID, this can only be done after the clocks + * are generated by the DPHY and the clock resets have been released. + */ + err = getmode(bridge, &mode); + if(err != nil) + goto out; + + /* allocates the framebuffer (gscreen->data->bdata) */ + if(screeninit(mode.hactive, mode.vactive, 32) < 0){ + err = "screeninit failed"; + goto out; + } + + /* start the pixel clock */ + setclkrate("lcdif.pix_clk", "system_pll1_clk", mode.pixclk); + dpiinit(&mode); + + /* release dpi reset */ + mr(resetc, SRC_MIPIPHY_RCR, RCR_MIPI_DSI_DPI_RESET_N, RCR_MIPI_DSI_DPI_RESET_N); + + /* enable display port bridge */ + bridgeinit(bridge, &mode, &dsi_cfg); + + /* send the pixels */ + lcdifinit(&mode); + return; + +out: + print("lcdinit: %s\n", err); +} diff --git a/sys/src/9/imx8/main.c b/sys/src/9/imx8/main.c index 01e4ce20c..b0494f682 100644 --- a/sys/src/9/imx8/main.c +++ b/sys/src/9/imx8/main.c @@ -32,6 +32,7 @@ init0(void) poperror(); } kproc("alarm", alarmkproc, 0); + sp = (char**)(USTKTOP-sizeof(Tos) - 8 - sizeof(sp[0])*4); sp[3] = sp[2] = sp[1] = nil; strcpy(sp[1] = (char*)&sp[4], "boot"); @@ -99,14 +100,7 @@ confinit(void) + conf.nswap + conf.nswppo*sizeof(Page*); mainmem->maxsize = kpages; - if(!cpuserver) - /* - * give terminals lots of image memory, too; the dynamic - * allocation will balance the load properly, hopefully. - * be careful with 32-bit overflow. - */ - imagmem->maxsize = kpages; - + imagmem->maxsize = kpages; } void @@ -149,7 +143,6 @@ main(void) fpuinit(); intrinit(); clockinit(); - print("cpu%d: UP!\n", m->machno); synccycles(); timersinit(); flushtlb(); @@ -175,6 +168,7 @@ main(void) initseg(); links(); chandevreset(); + lcdinit(); userinit(); mpinit(); mmu0clear((uintptr*)L1); diff --git a/sys/src/9/imx8/mem.h b/sys/src/9/imx8/mem.h index f20037bd9..0c92e9ae2 100644 --- a/sys/src/9/imx8/mem.h +++ b/sys/src/9/imx8/mem.h @@ -39,9 +39,9 @@ #define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */ #define TRAPFRAMESIZE (38*8) -/* reserved dram for ucalloc() at the end of KZERO (physical) */ +/* reserved dram for ucalloc() and fbmemalloc() at the end of KZERO (physical) */ #define UCRAMBASE (-KZERO - UCRAMSIZE) -#define UCRAMSIZE (1*MiB) +#define UCRAMSIZE (8*MiB) #define VDRAM (0xFFFFFFFFC0000000ULL) /* 0x40000000 - 0x80000000 */ #define KTZERO (VDRAM + 0x100000) /* kernel text start */ @@ -54,7 +54,7 @@ #define VMAP (0xFFFFFFFF00000000ULL) /* 0x00000000 - 0x40000000 */ #define KMAPEND (0xFFFFFFFF00000000ULL) /* 0x140000000 */ -#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ +#define KMAP (0xFFFFFFFE00000000ULL) /* 0x40000000 */ #define KSEG0 (0xFFFFFFFE00000000ULL) diff --git a/sys/src/9/imx8/mkfile b/sys/src/9/imx8/mkfile index 2e37a5a8b..01f8adad6 100644 --- a/sys/src/9/imx8/mkfile +++ b/sys/src/9/imx8/mkfile @@ -58,12 +58,12 @@ OBJ=\ # HFILES= LIB=\ -# /$objtype/lib/libmemlayer.a\ -# /$objtype/lib/libmemdraw.a\ -# /$objtype/lib/libdraw.a\ + /$objtype/lib/libmemlayer.a\ + /$objtype/lib/libmemdraw.a\ + /$objtype/lib/libdraw.a\ /$objtype/lib/libip.a\ /$objtype/lib/libsec.a\ -# /$objtype/lib/libmp.a\ + /$objtype/lib/libmp.a\ /$objtype/lib/libc.a\ # /$objtype/lib/libdtracy.a\ diff --git a/sys/src/9/imx8/mmu.c b/sys/src/9/imx8/mmu.c index 5bec2ab05..c61ca7f01 100644 --- a/sys/src/9/imx8/mmu.c +++ b/sys/src/9/imx8/mmu.c @@ -472,21 +472,36 @@ checkmmu(uintptr, uintptr) { } -void* -ucalloc(usize size) +static void* +ucramalloc(usize size, uintptr align, uint attr) { static uintptr top = UCRAMBASE + UCRAMSIZE; static Lock lk; - uintptr va; - - size = PGROUND(size); + uintptr va, pg; lock(&lk); top -= size; + size += top & align-1; + top &= -align; if(top < UCRAMBASE) - panic("ucalloc: %p needs %zd bytes\n", getcallerpc(&size), size); + panic("ucramalloc: need %zd bytes", size); va = KZERO + top; + pg = va & -BY2PG; + if(pg != ((va+size) & -BY2PG)) + mmukmap(pg | attr, pg - KZERO, PGROUND(size)); unlock(&lk); - return (void*)mmukmap(va | PTEUNCACHED, PADDR(va), size); + return (void*)va; +} + +void* +ucalloc(usize size) +{ + return ucramalloc(size, 8, PTEUNCACHED); +} + +void* +fbmemalloc(usize size) +{ + return ucramalloc(PGROUND(size), BY2PG, PTEWT); } diff --git a/sys/src/9/imx8/reform b/sys/src/9/imx8/reform index ae88c1d99..64a012e7d 100644 --- a/sys/src/9/imx8/reform +++ b/sys/src/9/imx8/reform @@ -14,14 +14,18 @@ dev fs ether netif ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium inferno + draw screen swcursor + mouse screen swcursor uart usb + i2c link usbxhciimx etherimx ethermii ethermedium loopbackmedium + i2cimx devi2c ip tcp udp @@ -31,8 +35,10 @@ ip icmp6 ipmux misc + ccm gic uartimx + lcd port int cpuserver = 0; bootdir diff --git a/sys/src/9/imx8/screen.c b/sys/src/9/imx8/screen.c new file mode 100644 index 000000000..5be30fa79 --- /dev/null +++ b/sys/src/9/imx8/screen.c @@ -0,0 +1,341 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" + +#define Image IMAGE +#include <draw.h> +#include <memdraw.h> +#include <cursor.h> +#include "screen.h" + +enum { + Tabstop = 4, + Scroll = 8, +}; + +Memimage *gscreen; + +static Memdata xgdata; +static Memimage xgscreen; +static Memimage *conscol; +static Memimage *back; +static Memsubfont *memdefont; + +static Lock screenlock; + +static Point curpos; +static int h, w; +static Rectangle window; + +static void myscreenputs(char *s, int n); +static void screenputc(char *buf); +static void screenwin(void); + +enum +{ + CMaccelerated, + CMlinear, +}; + +static Cmdtab mousectlmsg[] = +{ + CMaccelerated, "accelerated", 0, + CMlinear, "linear", 1, +}; + +void +mousectl(Cmdbuf *cb) +{ + Cmdtab *ct; + + ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg)); + switch(ct->index){ + case CMaccelerated: + mouseaccelerate(cb->nf == 1? 1: atoi(cb->f[1])); + break; + case CMlinear: + mouseaccelerate(0); + break; + } +} + +void +cursoron(void) +{ + swcursorhide(0); + swcursordraw(mousexy()); +} + +void +cursoroff(void) +{ + swcursorhide(0); +} + +void +setcursor(Cursor* curs) +{ + swcursorload(curs); +} + +int +hwdraw(Memdrawparam *par) +{ + Memimage *dst, *src, *mask; + + if((dst = par->dst) == nil || dst->data == nil) + return 0; + if((src = par->src) && src->data == nil) + src = nil; + if((mask = par->mask) && mask->data == nil) + mask = nil; + + if(dst->data->bdata == xgdata.bdata) + swcursoravoid(par->r); + if(src && src->data->bdata == xgdata.bdata) + swcursoravoid(par->sr); + if(mask && mask->data->bdata == xgdata.bdata) + swcursoravoid(par->mr); + + return 0; +} + +int +screeninit(int width, int height, int depth) +{ + ulong chan; + + switch(depth){ + default: + return -1; + case 32: + chan = XRGB32; + break; + case 24: + chan = RGB24; + break; + case 16: + chan = RGB16; + break; + } + memsetchan(&xgscreen, chan); + xgscreen.r = Rect(0, 0, width, height); + xgscreen.clipr = xgscreen.r; + xgscreen.depth = depth; + xgscreen.width = wordsperline(xgscreen.r, xgscreen.depth); + xgdata.bdata = fbmemalloc(xgscreen.width*sizeof(ulong)*height); + xgdata.ref = 1; + + xgscreen.data = &xgdata; + + gscreen = &xgscreen; + + conf.monitor = 1; + + memimageinit(); + memdefont = getmemdefont(); + screenwin(); + myscreenputs(kmesg.buf, kmesg.n); + screenputs = myscreenputs; + swcursorinit(); + + return 0; +} + +void +flushmemscreen(Rectangle) +{ +} + +Memdata* +attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen) +{ + if(gscreen == nil) + return nil; + + *r = gscreen->r; + *d = gscreen->depth; + *chan = gscreen->chan; + *width = gscreen->width; + *softscreen = 0; + + gscreen->data->ref++; + return gscreen->data; +} + +void +getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) +{ + USED(p, pr, pg, pb); +} + +int +setcolor(ulong p, ulong r, ulong g, ulong b) +{ + USED(p, r, g, b); + return 0; +} + +void +blankscreen(int) +{ +} + +static void +myscreenputs(char *s, int n) +{ + int i; + Rune r; + char buf[4]; + + if(!islo()) { + /* don't deadlock trying to print in interrupt */ + if(!canlock(&screenlock)) + return; + } + else + lock(&screenlock); + + while(n > 0){ + i = chartorune(&r, s); + if(i == 0){ + s++; + --n; + continue; + } + memmove(buf, s, i); + buf[i] = 0; + n -= i; + s += i; + screenputc(buf); + } + unlock(&screenlock); +} + +static void +screenwin(void) +{ + char *greet; + Memimage *orange; + Point p, q; + Rectangle r; + + back = memblack; + conscol = memwhite; + + orange = allocmemimage(Rect(0, 0, 1, 1), RGB16); + orange->flags |= Frepl; + orange->clipr = gscreen->r; + orange->data->bdata[0] = 0x40; /* magic: colour? */ + orange->data->bdata[1] = 0xfd; /* magic: colour? */ + + w = memdefont->info[' '].width; + h = memdefont->height; + + r = gscreen->r; + memimagedraw(gscreen, r, memwhite, ZP, memopaque, ZP, S); + window = insetrect(r, 4); + memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); + + memimagedraw(gscreen, Rect(window.min.x, window.min.y, + window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S); + + freememimage(orange); + window = insetrect(window, 5); + + greet = " Plan 9 Console "; + p = addpt(window.min, Pt(10, 0)); + q = memsubfontwidth(memdefont, greet); + memimagestring(gscreen, p, conscol, ZP, memdefont, greet); + flushmemscreen(r); + window.min.y += h + 6; + curpos = window.min; + window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h; +} + +static void +scroll(void) +{ + int o; + Point p; + Rectangle r; + + o = Scroll*h; + r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); + p = Pt(window.min.x, window.min.y+o); + memimagedraw(gscreen, r, gscreen, p, nil, p, S); + flushmemscreen(r); + r = Rpt(Pt(window.min.x, window.max.y-o), window.max); + memimagedraw(gscreen, r, back, ZP, nil, ZP, S); + flushmemscreen(r); + + curpos.y -= o; +} + +static void +screenputc(char *buf) +{ + int w; + uint pos; + Point p; + Rectangle r; + static int *xp; + static int xbuf[256]; + + if (xp < xbuf || xp >= &xbuf[nelem(xbuf)]) + xp = xbuf; + + switch (buf[0]) { + case '\n': + if (curpos.y + h >= window.max.y) + scroll(); + curpos.y += h; + screenputc("\r"); + break; + case '\r': + xp = xbuf; + curpos.x = window.min.x; + break; + case '\t': + p = memsubfontwidth(memdefont, " "); + w = p.x; + if (curpos.x >= window.max.x - Tabstop * w) + screenputc("\n"); + + pos = (curpos.x - window.min.x) / w; + pos = Tabstop - pos % Tabstop; + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + flushmemscreen(r); + curpos.x += pos * w; + break; + case '\b': + if (xp <= xbuf) + break; + xp--; + r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + flushmemscreen(r); + curpos.x = *xp; + break; + case '\0': + break; + default: + p = memsubfontwidth(memdefont, buf); + w = p.x; + + if (curpos.x >= window.max.x - w) + screenputc("\n"); + + *xp++ = curpos.x; + r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h); + memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S); + memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); + flushmemscreen(r); + curpos.x += w; + break; + } +} diff --git a/sys/src/9/imx8/screen.h b/sys/src/9/imx8/screen.h new file mode 100644 index 000000000..fc0b7f582 --- /dev/null +++ b/sys/src/9/imx8/screen.h @@ -0,0 +1,32 @@ +/* devmouse.c */ +typedef struct Cursor Cursor; +extern Cursor cursor; +extern void mousetrack(int, int, int, ulong); +extern void absmousetrack(int, int, int, ulong); +extern Point mousexy(void); +extern void mouseaccelerate(int); + +/* screen.c */ +extern int screeninit(int width, int hight, int depth); +extern void blankscreen(int); +extern void flushmemscreen(Rectangle); +extern Memdata* attachscreen(Rectangle*, ulong*, int*, int*, int*); +extern void cursoron(void); +extern void cursoroff(void); +extern void setcursor(Cursor*); + +extern void mousectl(Cmdbuf*); +extern void mouseresize(void); +extern void mouseredraw(void); + +/* devdraw.c */ +extern QLock drawlock; + +#define ishwimage(i) 1 /* for ../port/devdraw.c */ + +/* swcursor.c */ +void swcursorhide(int); +void swcursoravoid(Rectangle); +void swcursordraw(Point); +void swcursorload(Cursor *); +void swcursorinit(void); diff --git a/sys/src/9/imx8/uartimx.c b/sys/src/9/imx8/uartimx.c index 5d6e0d2f1..c7173f423 100644 --- a/sys/src/9/imx8/uartimx.c +++ b/sys/src/9/imx8/uartimx.c @@ -315,17 +315,35 @@ interrupt(Ureg*, void *arg) } static void +clkenable(Uart *u, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "%s.ipg_perclk", u->name); + if(on) setclkrate(clk, "osc_25m_ref_clk", u->freq); + setclkgate(clk, on); +} + +static void disable(Uart *u) { u32int *regs = u->regs; + + if(u->console) + return; /* avoid glitch */ + regs[UCR1] = 0; + clkenable(u, 0); } static void enable(Uart *u, int ie) { disable(u); + clkenable(u, 1); + if(ie) intrenable(IRQuart1, interrupt, u, BUSUNKNOWN, u->name); + config(u); } diff --git a/sys/src/9/imx8/usbxhciimx.c b/sys/src/9/imx8/usbxhciimx.c index e08b80b19..6eebb3dfe 100644 --- a/sys/src/9/imx8/usbxhciimx.c +++ b/sys/src/9/imx8/usbxhciimx.c @@ -1774,6 +1774,17 @@ portreset(Hci *hp, int port, int on) return 0; } +static void +clkenable(int i, int on) +{ + char clk[32]; + + snprint(clk, sizeof(clk), "usb%d.ctrl", i+1); + setclkgate(clk, on); + snprint(clk, sizeof(clk), "usb%d.phy", i+1); + setclkgate(clk, on); +} + static int reset(Hci *hp) { @@ -1796,6 +1807,15 @@ reset(Hci *hp) return -1; Found: + if(i == 0){ + 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; + } + clkenable(i, 1); + hp->init = init; hp->dump = dump; hp->interrupt = interrupt; |