linux/drivers/clk/qcom/gcc-ipq4019.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2015 The Linux Foundation. All rights reserved.
 */

#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include <linux/math64.h>
#include <linux/delay.h>
#include <linux/clk.h>

#include <dt-bindings/clock/qcom,gcc-ipq4019.h>

#include "common.h"
#include "clk-regmap.h"
#include "clk-rcg.h"
#include "clk-branch.h"
#include "reset.h"
#include "clk-regmap-divider.h"

#define to_clk_regmap_div(_hw)

#define to_clk_fepll(_hw)

enum {};

/*
 * struct clk_fepll_vco - vco feedback divider corresponds for FEPLL clocks
 * @fdbkdiv_shift: lowest bit for FDBKDIV
 * @fdbkdiv_width: number of bits in FDBKDIV
 * @refclkdiv_shift: lowest bit for REFCLKDIV
 * @refclkdiv_width: number of bits in REFCLKDIV
 * @reg: PLL_DIV register address
 */
struct clk_fepll_vco {};

/*
 * struct clk_fepll - clk divider corresponds to FEPLL clocks
 * @fixed_div: fixed divider value if divider is fixed
 * @parent_map: map from software's parent index to hardware's src_sel field
 * @cdiv: divider values for PLL_DIV
 * @pll_vco: vco feedback divider
 * @div_table: mapping for actual divider value to register divider value
 *             in case of non fixed divider
 * @freq_tbl: frequency table
 */
struct clk_fepll {};

/*
 * Contains index for safe clock during APSS freq change.
 * fepll500 is being used as safe clock so initialize it
 * with its index in parents list gcc_xo_ddr_500_200.
 */
static const int gcc_ipq4019_cpu_safe_parent =;

/* Calculates the VCO rate for FEPLL. */
static u64 clk_fepll_vco_calc_rate(struct clk_fepll *pll_div,
				   unsigned long parent_rate)
{}

static const struct clk_fepll_vco gcc_apss_ddrpll_vco =;

static const struct clk_fepll_vco gcc_fepll_vco =;

/*
 * Round rate function for APSS CPU PLL Clock divider.
 * It looks up the frequency table and returns the next higher frequency
 * supported in hardware.
 */
static long clk_cpu_div_round_rate(struct clk_hw *hw, unsigned long rate,
				   unsigned long *p_rate)
{
	struct clk_fepll *pll = to_clk_fepll(hw);
	struct clk_hw *p_hw;
	const struct freq_tbl *f;

	f = qcom_find_freq(pll->freq_tbl, rate);
	if (!f)
		return -EINVAL;

	p_hw = clk_hw_get_parent_by_index(hw, f->src);
	*p_rate = clk_hw_get_rate(p_hw);

	return f->freq;
};

/*
 * Clock set rate function for APSS CPU PLL Clock divider.
 * It looks up the frequency table and updates the PLL divider to corresponding
 * divider value.
 */
static int clk_cpu_div_set_rate(struct clk_hw *hw, unsigned long rate,
				unsigned long parent_rate)
{
	struct clk_fepll *pll = to_clk_fepll(hw);
	const struct freq_tbl *f;
	u32 mask;

	f = qcom_find_freq(pll->freq_tbl, rate);
	if (!f)
		return -EINVAL;

	mask = (BIT(pll->cdiv.width) - 1) << pll->cdiv.shift;
	regmap_update_bits(pll->cdiv.clkr.regmap,
			   pll->cdiv.reg, mask,
			   f->pre_div << pll->cdiv.shift);
	/*
	 * There is no status bit which can be checked for successful CPU
	 * divider update operation so using delay for the same.
	 */
	udelay(1);

	return 0;
};

/*
 * Clock frequency calculation function for APSS CPU PLL Clock divider.
 * This clock divider is nonlinear so this function calculates the actual
 * divider and returns the output frequency by dividing VCO Frequency
 * with this actual divider value.
 */
static unsigned long
clk_cpu_div_recalc_rate(struct clk_hw *hw,
			unsigned long parent_rate)
{
	struct clk_fepll *pll = to_clk_fepll(hw);
	u32 cdiv, pre_div;
	u64 rate;

	regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
	cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);

	/*
	 * Some dividers have value in 0.5 fraction so multiply both VCO
	 * frequency(parent_rate) and pre_div with 2 to make integer
	 * calculation.
	 */
	if (cdiv > 10)
		pre_div = (cdiv + 1) * 2;
	else
		pre_div = cdiv + 12;

	rate = clk_fepll_vco_calc_rate(pll, parent_rate) * 2;
	do_div(rate, pre_div);

	return rate;
};

static const struct clk_ops clk_regmap_cpu_div_ops =;

static const struct freq_tbl ftbl_apss_ddr_pll[] =;

static struct clk_fepll gcc_apss_cpu_plldiv_clk =;

/* Calculates the rate for PLL divider.
 * If the divider value is not fixed then it gets the actual divider value
 * from divider table. Then, it calculate the clock rate by dividing the
 * parent rate with actual divider value.
 */
static unsigned long
clk_regmap_clk_div_recalc_rate(struct clk_hw *hw,
			       unsigned long parent_rate)
{
	struct clk_fepll *pll = to_clk_fepll(hw);
	u32 cdiv, pre_div = 1;
	u64 rate;
	const struct clk_div_table *clkt;

	if (pll->fixed_div) {
		pre_div = pll->fixed_div;
	} else {
		regmap_read(pll->cdiv.clkr.regmap, pll->cdiv.reg, &cdiv);
		cdiv = (cdiv >> pll->cdiv.shift) & (BIT(pll->cdiv.width) - 1);

		for (clkt = pll->div_table; clkt->div; clkt++) {
			if (clkt->val == cdiv)
				pre_div = clkt->div;
		}
	}

	rate = clk_fepll_vco_calc_rate(pll, parent_rate);
	do_div(rate, pre_div);

	return rate;
};

static const struct clk_ops clk_fepll_div_ops =;

static struct clk_fepll gcc_apss_sdcc_clk =;

static struct clk_fepll gcc_fepll125_clk =;

static struct clk_fepll gcc_fepll125dly_clk =;

static struct clk_fepll gcc_fepll200_clk =;

static struct clk_fepll gcc_fepll500_clk =;

static const struct clk_div_table fepllwcss_clk_div_table[] =;

static struct clk_fepll gcc_fepllwcss2g_clk =;

static struct clk_fepll gcc_fepllwcss5g_clk =;

static struct parent_map gcc_xo_200_500_map[] =;

static const struct clk_parent_data gcc_xo_200_500[] =;

static const struct freq_tbl ftbl_gcc_pcnoc_ahb_clk[] =;

static struct clk_rcg2 gcc_pcnoc_ahb_clk_src =;

static struct clk_branch pcnoc_clk_src =;

static struct parent_map gcc_xo_200_map[] =;

static const struct clk_parent_data gcc_xo_200[] =;

static const struct freq_tbl ftbl_gcc_audio_pwm_clk[] =;

static struct clk_rcg2 audio_clk_src =;

static struct clk_branch gcc_audio_ahb_clk =;

static struct clk_branch gcc_audio_pwm_clk =;

static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_i2c_apps_clk[] =;

static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src =;

static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk =;

static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src =;

static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk =;

static struct parent_map gcc_xo_200_spi_map[] =;

static const struct clk_parent_data gcc_xo_200_spi[] =;

static const struct freq_tbl ftbl_gcc_blsp1_qup1_2_spi_apps_clk[] =;

static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src =;

static struct clk_branch gcc_blsp1_qup1_spi_apps_clk =;

static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src =;

static struct clk_branch gcc_blsp1_qup2_spi_apps_clk =;

static const struct freq_tbl ftbl_gcc_blsp1_uart1_2_apps_clk[] =;

static struct clk_rcg2 blsp1_uart1_apps_clk_src =;

static struct clk_branch gcc_blsp1_uart1_apps_clk =;

static struct clk_rcg2 blsp1_uart2_apps_clk_src =;

static struct clk_branch gcc_blsp1_uart2_apps_clk =;

static const struct freq_tbl ftbl_gcc_gp_clk[] =;

static struct clk_rcg2 gp1_clk_src =;

static struct clk_branch gcc_gp1_clk =;

static struct clk_rcg2 gp2_clk_src =;

static struct clk_branch gcc_gp2_clk =;

static struct clk_rcg2 gp3_clk_src =;

static struct clk_branch gcc_gp3_clk =;

static struct parent_map gcc_xo_sdcc1_500_map[] =;

static const struct clk_parent_data gcc_xo_sdcc1_500[] =;

static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] =;

static struct clk_rcg2  sdcc1_apps_clk_src =;

static const struct freq_tbl ftbl_gcc_apps_clk[] =;

static struct parent_map gcc_xo_ddr_500_200_map[] =;

static const struct clk_parent_data gcc_xo_ddr_500_200[] =;

static struct clk_rcg2 apps_clk_src =;

static const struct freq_tbl ftbl_gcc_apps_ahb_clk[] =;

static struct clk_rcg2 apps_ahb_clk_src =;

static struct clk_branch gcc_apss_ahb_clk =;

static struct clk_branch gcc_blsp1_ahb_clk =;

static struct clk_branch gcc_dcd_xo_clk =;

static struct clk_branch gcc_boot_rom_ahb_clk =;

static struct clk_branch gcc_crypto_ahb_clk =;

static struct clk_branch gcc_crypto_axi_clk =;

static struct clk_branch gcc_crypto_clk =;

static struct parent_map gcc_xo_125_dly_map[] =;

static const struct clk_parent_data gcc_xo_125_dly[] =;

static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] =;

static struct clk_rcg2 fephy_125m_dly_clk_src =;

static struct clk_branch gcc_ess_clk =;

static struct clk_branch gcc_imem_axi_clk =;

static struct clk_branch gcc_imem_cfg_ahb_clk =;

static struct clk_branch gcc_pcie_ahb_clk =;

static struct clk_branch gcc_pcie_axi_m_clk =;

static struct clk_branch gcc_pcie_axi_s_clk =;

static struct clk_branch gcc_prng_ahb_clk =;

static struct clk_branch gcc_qpic_ahb_clk =;

static struct clk_branch gcc_qpic_clk =;

static struct clk_branch gcc_sdcc1_ahb_clk =;

static struct clk_branch gcc_sdcc1_apps_clk =;

static struct clk_branch gcc_tlmm_ahb_clk =;

static struct clk_branch gcc_usb2_master_clk =;

static struct clk_branch gcc_usb2_sleep_clk =;

static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] =;

static struct clk_rcg2 usb30_mock_utmi_clk_src =;

static struct clk_branch gcc_usb2_mock_utmi_clk =;

static struct clk_branch gcc_usb3_master_clk =;

static struct clk_branch gcc_usb3_sleep_clk =;

static struct clk_branch gcc_usb3_mock_utmi_clk =;

static struct parent_map gcc_xo_wcss2g_map[] =;

static const struct clk_parent_data gcc_xo_wcss2g[] =;

static const struct freq_tbl ftbl_gcc_wcss2g_clk[] =;

static struct clk_rcg2 wcss2g_clk_src =;

static struct clk_branch gcc_wcss2g_clk =;

static struct clk_branch gcc_wcss2g_ref_clk =;

static struct clk_branch gcc_wcss2g_rtc_clk =;

static struct parent_map gcc_xo_wcss5g_map[] =;

static const struct clk_parent_data gcc_xo_wcss5g[] =;

static const struct freq_tbl ftbl_gcc_wcss5g_clk[] =;

static struct clk_rcg2 wcss5g_clk_src =;

static struct clk_branch gcc_wcss5g_clk =;

static struct clk_branch gcc_wcss5g_ref_clk =;

static struct clk_branch gcc_wcss5g_rtc_clk =;

static struct clk_regmap *gcc_ipq4019_clocks[] =;

static const struct qcom_reset_map gcc_ipq4019_resets[] =;

static const struct regmap_config gcc_ipq4019_regmap_config =;

static const struct qcom_cc_desc gcc_ipq4019_desc =;

static const struct of_device_id gcc_ipq4019_match_table[] =;
MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table);

static int
gcc_ipq4019_cpu_clk_notifier_fn(struct notifier_block *nb,
				unsigned long action, void *data)
{}

static struct notifier_block gcc_ipq4019_cpu_clk_notifier =;

static int gcc_ipq4019_probe(struct platform_device *pdev)
{}

static struct platform_driver gcc_ipq4019_driver =;

static int __init gcc_ipq4019_init(void)
{}
core_initcall(gcc_ipq4019_init);

static void __exit gcc_ipq4019_exit(void)
{}
module_exit(gcc_ipq4019_exit);

MODULE_ALIAS();
MODULE_LICENSE();
MODULE_DESCRIPTION();