static void __init stm32h7_rcc_init()

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);
}