in clk-stm32h7.c [1196:1390]
static void __init stm32h7_rcc_init(struct device_node *np)
{
struct clk_hw_onecell_data *clk_data;
struct composite_cfg c_cfg;
int n;
const char *hse_clk, *lse_clk, *i2s_clk;
struct regmap *pdrm;
clk_data = kzalloc(struct_size(clk_data, hws, STM32H7_MAX_CLKS),
GFP_KERNEL);
if (!clk_data)
return;
clk_data->num = STM32H7_MAX_CLKS;
hws = clk_data->hws;
for (n = 0; n < STM32H7_MAX_CLKS; n++)
hws[n] = ERR_PTR(-ENOENT);
/* get RCC base @ from DT */
base = of_iomap(np, 0);
if (!base) {
pr_err("%pOFn: unable to map resource", np);
goto err_free_clks;
}
pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
if (IS_ERR(pdrm))
pr_warn("%s: Unable to get syscfg\n", __func__);
else
/* In any case disable backup domain write protection
* and will never be enabled.
* Needed by LSE & RTC clocks.
*/
regmap_update_bits(pdrm, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
/* Put parent names from DT */
hse_clk = of_clk_get_parent_name(np, 0);
lse_clk = of_clk_get_parent_name(np, 1);
i2s_clk = of_clk_get_parent_name(np, 2);
sai_src[3] = i2s_clk;
spi_src1[3] = i2s_clk;
/* Register Internal oscillators */
clk_hw_register_fixed_rate(NULL, "clk-hsi", NULL, 0, 64000000);
clk_hw_register_fixed_rate(NULL, "clk-csi", NULL, 0, 4000000);
clk_hw_register_fixed_rate(NULL, "clk-lsi", NULL, 0, 32000);
clk_hw_register_fixed_rate(NULL, "clk-rc48", NULL, 0, 48000);
/* This clock is coming from outside. Frequencies unknown */
hws[CK_DSI_PHY] = clk_hw_register_fixed_rate(NULL, "ck_dsi_phy", NULL,
0, 0);
hws[HSI_DIV] = clk_hw_register_divider(NULL, "hsidiv", "clk-hsi", 0,
base + RCC_CR, 3, 2, CLK_DIVIDER_POWER_OF_TWO,
&stm32rcc_lock);
hws[HSE_1M] = clk_hw_register_divider(NULL, "hse_1M", "hse_ck", 0,
base + RCC_CFGR, 8, 6, CLK_DIVIDER_ONE_BASED |
CLK_DIVIDER_ALLOW_ZERO,
&stm32rcc_lock);
/* Mux system clocks */
for (n = 0; n < ARRAY_SIZE(stm32_mclk); n++)
hws[MCLK_BANK + n] = clk_hw_register_mux(NULL,
stm32_mclk[n].name,
stm32_mclk[n].parents,
stm32_mclk[n].num_parents,
stm32_mclk[n].flags,
stm32_mclk[n].offset + base,
stm32_mclk[n].shift,
stm32_mclk[n].width,
0,
&stm32rcc_lock);
register_core_and_bus_clocks();
/* Oscillary clocks */
for (n = 0; n < ARRAY_SIZE(stm32_oclk); n++)
hws[OSC_BANK + n] = clk_register_ready_gate(NULL,
stm32_oclk[n].name,
stm32_oclk[n].parent,
stm32_oclk[n].gate_offset + base,
stm32_oclk[n].bit_idx,
stm32_oclk[n].bit_rdy,
stm32_oclk[n].flags,
&stm32rcc_lock);
hws[HSE_CK] = clk_register_ready_gate(NULL,
"hse_ck",
hse_clk,
RCC_CR + base,
16, 17,
0,
&stm32rcc_lock);
hws[LSE_CK] = clk_register_ready_gate(NULL,
"lse_ck",
lse_clk,
RCC_BDCR + base,
0, 1,
0,
&stm32rcc_lock);
hws[CSI_KER_DIV122 + n] = clk_hw_register_fixed_factor(NULL,
"csi_ker_div122", "csi_ker", 0, 1, 122);
/* PLLs */
for (n = 0; n < ARRAY_SIZE(stm32_pll); n++) {
int odf;
/* Register the VCO */
clk_register_stm32_pll(NULL, stm32_pll[n].name,
stm32_pll[n].parent_name, stm32_pll[n].flags,
stm32_pll[n].cfg,
&stm32rcc_lock);
/* Register the 3 output dividers */
for (odf = 0; odf < 3; odf++) {
int idx = n * 3 + odf;
get_cfg_composite_div(&odf_clk_gcfg, &stm32_odf[n][odf],
&c_cfg, &stm32rcc_lock);
hws[ODF_BANK + idx] = clk_hw_register_composite(NULL,
stm32_odf[n][odf].name,
stm32_odf[n][odf].parent_name,
stm32_odf[n][odf].num_parents,
c_cfg.mux_hw, c_cfg.mux_ops,
c_cfg.div_hw, c_cfg.div_ops,
c_cfg.gate_hw, c_cfg.gate_ops,
stm32_odf[n][odf].flags);
}
}
/* Peripheral clocks */
for (n = 0; n < ARRAY_SIZE(pclk); n++)
hws[PERIF_BANK + n] = clk_hw_register_gate(NULL, pclk[n].name,
pclk[n].parent,
pclk[n].flags, base + pclk[n].gate_offset,
pclk[n].bit_idx, pclk[n].flags, &stm32rcc_lock);
/* Kernel clocks */
for (n = 0; n < ARRAY_SIZE(kclk); n++) {
get_cfg_composite_div(&kernel_clk_cfg, &kclk[n], &c_cfg,
&stm32rcc_lock);
hws[KERN_BANK + n] = clk_hw_register_composite(NULL,
kclk[n].name,
kclk[n].parent_name,
kclk[n].num_parents,
c_cfg.mux_hw, c_cfg.mux_ops,
c_cfg.div_hw, c_cfg.div_ops,
c_cfg.gate_hw, c_cfg.gate_ops,
kclk[n].flags);
}
/* RTC clock (default state is off) */
clk_hw_register_fixed_rate(NULL, "off", NULL, 0, 0);
get_cfg_composite_div(&rtc_clk_cfg, &rtc_clk, &c_cfg, &stm32rcc_lock);
hws[RTC_CK] = clk_hw_register_composite(NULL,
rtc_clk.name,
rtc_clk.parent_name,
rtc_clk.num_parents,
c_cfg.mux_hw, c_cfg.mux_ops,
c_cfg.div_hw, c_cfg.div_ops,
c_cfg.gate_hw, c_cfg.gate_ops,
rtc_clk.flags);
/* Micro-controller clocks */
for (n = 0; n < ARRAY_SIZE(mco_clk); n++) {
get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg,
&stm32rcc_lock);
hws[MCO_BANK + n] = clk_hw_register_composite(NULL,
mco_clk[n].name,
mco_clk[n].parent_name,
mco_clk[n].num_parents,
c_cfg.mux_hw, c_cfg.mux_ops,
c_cfg.div_hw, c_cfg.div_ops,
c_cfg.gate_hw, c_cfg.gate_ops,
mco_clk[n].flags);
}
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
return;
err_free_clks:
kfree(clk_data);
}