Commit 420b2d43 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk fixes from Stephen Boyd:
 "Two clk driver fixes

   - Use devm_kasprintf() to avoid overflows when forming clk names in
     the Microchip PolarFire driver

   - Fix the pretty broken Ingenic JZ4760 M/N/OD calculation to actually
     work and find proper divisors"

* tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux:
  clk: ingenic: jz4760: Update M/N/OD calculation algorithm
  clk: microchip: mpfs-ccc: Use devm_kasprintf() for allocating formatted strings
parents 545c80ab ecfb9f40
Loading
Loading
Loading
Loading
+8 −10
Original line number Diff line number Diff line
@@ -58,7 +58,7 @@ jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
		       unsigned long rate, unsigned long parent_rate,
		       unsigned int *pm, unsigned int *pn, unsigned int *pod)
{
	unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 2;
	unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 1;

	/* The frequency after the N divider must be between 1 and 50 MHz. */
	n = parent_rate / (1 * MHZ);
@@ -66,19 +66,17 @@ jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
	/* The N divider must be >= 2. */
	n = clamp_val(n, 2, 1 << pll_info->n_bits);

	for (;; n >>= 1) {
		od = (unsigned int)-1;
	rate /= MHZ;
	parent_rate /= MHZ;

		do {
			m = (rate / MHZ) * (1 << ++od) * n / (parent_rate / MHZ);
		} while ((m > m_max || m & 1) && (od < 4));

		if (od < 4 && m >= 4 && m <= m_max)
			break;
	for (m = m_max; m >= m_max && n >= 2; n--) {
		m = rate * n / parent_rate;
		od = m & 1;
		m <<= od;
	}

	*pm = m;
	*pn = n;
	*pn = n + 1;
	*pod = 1 << od;
}

+4 −6
Original line number Diff line number Diff line
@@ -164,12 +164,11 @@ static int mpfs_ccc_register_outputs(struct device *dev, struct mpfs_ccc_out_hw_

	for (unsigned int i = 0; i < num_clks; i++) {
		struct mpfs_ccc_out_hw_clock *out_hw = &out_hws[i];
		char *name = devm_kzalloc(dev, 23, GFP_KERNEL);
		char *name = devm_kasprintf(dev, GFP_KERNEL, "%s_out%u", parent->name, i);

		if (!name)
			return -ENOMEM;

		snprintf(name, 23, "%s_out%u", parent->name, i);
		out_hw->divider.hw.init = CLK_HW_INIT_HW(name, &parent->hw, &clk_divider_ops, 0);
		out_hw->divider.reg = data->pll_base[i / MPFS_CCC_OUTPUTS_PER_PLL] +
			out_hw->reg_offset;
@@ -201,14 +200,13 @@ static int mpfs_ccc_register_plls(struct device *dev, struct mpfs_ccc_pll_hw_clo

	for (unsigned int i = 0; i < num_clks; i++) {
		struct mpfs_ccc_pll_hw_clock *pll_hw = &pll_hws[i];
		char *name = devm_kzalloc(dev, 18, GFP_KERNEL);

		if (!name)
		pll_hw->name = devm_kasprintf(dev, GFP_KERNEL, "ccc%s_pll%u",
					      strchrnul(dev->of_node->full_name, '@'), i);
		if (!pll_hw->name)
			return -ENOMEM;

		pll_hw->base = data->pll_base[i];
		snprintf(name, 18, "ccc%s_pll%u", strchrnul(dev->of_node->full_name, '@'), i);
		pll_hw->name = (const char *)name;
		pll_hw->hw.init = CLK_HW_INIT_PARENTS_DATA_FIXED_SIZE(pll_hw->name,
								      pll_hw->parents,
								      &mpfs_ccc_pll_ops, 0);