diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-07-03 11:36:50 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-07-03 11:36:50 +0000 |
commit | 548a48d1561dd77dbc082dddf0f9a2776ee91914 (patch) | |
tree | 5d8df94bd49aa1d186b2a2e2cf97f79f757e148f /sys/src/9/imx8/ccm.c | |
parent | e39d9249076e9a95e97b33313be1ab2e23095f1d (diff) |
imx8: pcie and nvme support
Diffstat (limited to 'sys/src/9/imx8/ccm.c')
-rw-r--r-- | sys/src/9/imx8/ccm.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/sys/src/9/imx8/ccm.c b/sys/src/9/imx8/ccm.c index ffec22d52..21a0321aa 100644 --- a/sys/src/9/imx8/ccm.c +++ b/sys/src/9/imx8/ccm.c @@ -1075,6 +1075,90 @@ enablepll(int input) } } +enum { + CCM_ANALOG_PLLOUT_MONITOR_CFG = 0x74/4, + PLLOUT_MONITOR_CLK_CKE = 1<<4, + CCM_ANALOG_FRAC_PLLOUT_DIV_CFG = 0x78/4, + CCM_ANALOG_SCCG_PLLOUT_DIV_CFG = 0x7C/4, +}; + +static struct { + uchar input; + uchar reg; /* divider register */ + uchar shift; /* divider shift */ +} anapllout_input[16] = { +[0] OSC_25M_REF_CLK, +[1] OSC_27M_REF_CLK, +/* [2] HDMI_PHY_27M_CLK */ +/* [3] CLK1_P_N */ +[4] OSC_32K_REF_CLK, +[5] AUDIO_PLL1_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 0, +[6] AUDIO_PLL2_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 4, +[7] GPU_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 12, +[8] VPU_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 16, +[9] VIDEO_PLL1_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 8, +[10] ARM_PLL_CLK, CCM_ANALOG_FRAC_PLLOUT_DIV_CFG, 20, +[11] SYSTEM_PLL1_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 0, +[12] SYSTEM_PLL2_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 4, +[13] SYSTEM_PLL3_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 8, +[14] VIDEO_PLL2_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 16, +[15] DRAM_PLL1_CLK, CCM_ANALOG_SCCG_PLLOUT_DIV_CFG, 12, +}; + +static void +setanapllout(int input, int freq) +{ + int mux, div, reg; + + for(mux = 0; mux < nelem(anapllout_input); mux++) + if(anapllout_input[mux].input == input) + goto Muxok; + panic("setanapllout: bad input clock\n"); + return; +Muxok: + anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG] = mux; + if(freq <= 0) + return; + div = input_clk_freq[input] / freq; + if(div < 1 || div > 8){ + panic("setanapllout: divider out of range\n"); + return; + } + enablepll(input); + reg = anapllout_input[mux].reg; + if(reg){ + int shift = anapllout_input[mux].shift; + anatop[reg] = (anatop[reg] & ~(7<<shift)) | ((div-1)<<shift); + } else if(div != 1){ + panic("setanapllout: bad frequency\n"); + return; + } + anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG] |= PLLOUT_MONITOR_CLK_CKE; +} + +static int +getanapllout(void) +{ + int mux, input, freq, reg, div; + u32int cfg = anatop[CCM_ANALOG_PLLOUT_MONITOR_CFG]; + + mux = cfg & 0xF; + input = anapllout_input[mux].input; + if(input == 0) + return 0; + freq = input_clk_freq[input]; + if((cfg & PLLOUT_MONITOR_CLK_CKE) == 0) + freq = -freq; + reg = anapllout_input[mux].reg; + if(reg){ + int shift = anapllout_input[mux].shift; + div = ((anatop[reg] >> shift) & 7)+1; + } else { + div = 1; + } + return freq / div; +} + static u32int clkgate(Clock *gate, u32int val) { @@ -1330,6 +1414,11 @@ setclkrate(char *name, char *source, int freq) { int root, input; + if(cistrcmp(name, "ccm_analog_pllout") == 0){ + setanapllout(lookinputclk(source), freq); + return; + } + if((root = lookrootclk(name)) < 0) panic("setclkrate: clock %s not defined", name); if(source == nil) @@ -1346,6 +1435,9 @@ getclkrate(char *name) { int root, input; + if(cistrcmp(name, "ccm_analog_pllout") == 0) + return getanapllout(); + if((root = lookrootclk(name)) >= 0) return rootclkgetcfg(root, &input); |