Commit e74581b7 authored by Stephen Boyd's avatar Stephen Boyd
Browse files

Merge tag 'meson-clk-4.21-2' of https://github.com/BayLibre/clk-meson into clk-meson

Pull more meson clk driver updates from Neil Armstrong:

 - Fix GXL HDMI Pll fractional bits (from first round)
 - Add the Meson8/Meson8b video clocks
 - Add clk-input helper and use it for axg-audio clock driver

* tag 'meson-clk-4.21-2' of https://github.com/BayLibre/clk-meson:
  clk: meson: axg-audio: use the clk input helper function
  clk: meson: add clk-input helper function
  clk: meson: meson8b: add the read-only video clock trees
  clk: meson: meson8b: add the fractional divider for vid_pll_dco
  clk: meson: meson8b: fix the offset of vid_pll_dco's N value
  clk: meson: Fix GXL HDMI PLL fractional bits width
parents 8913e8a7 f03566d0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
#

obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.o
obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-input.o
obj-$(CONFIG_COMMON_CLK_AMLOGIC_AUDIO)	+= clk-triphase.o sclk-div.o
obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
+24 −59
Original line number Diff line number Diff line
@@ -631,22 +631,23 @@ static struct clk_regmap *const axg_audio_clk_regmaps[] = {
	&axg_tdmout_c_lrclk,
};

static struct clk *devm_clk_get_enable(struct device *dev, char *id)
static int devm_clk_get_enable(struct device *dev, char *id)
{
	struct clk *clk;
	int ret;

	clk = devm_clk_get(dev, id);
	if (IS_ERR(clk)) {
		if (PTR_ERR(clk) != -EPROBE_DEFER)
		ret = PTR_ERR(clk);
		if (ret != -EPROBE_DEFER)
			dev_err(dev, "failed to get %s", id);
		return clk;
		return ret;
	}

	ret = clk_prepare_enable(clk);
	if (ret) {
		dev_err(dev, "failed to enable %s", id);
		return ERR_PTR(ret);
		return ret;
	}

	ret = devm_add_action_or_reset(dev,
@@ -654,74 +655,40 @@ static struct clk *devm_clk_get_enable(struct device *dev, char *id)
				       clk);
	if (ret) {
		dev_err(dev, "failed to add reset action on %s", id);
		return ERR_PTR(ret);
		return ret;
	}

	return clk;
	return 0;
}

static const struct clk_ops axg_clk_no_ops = {};

static struct clk_hw *axg_clk_hw_register_bypass(struct device *dev,
static int axg_register_clk_hw_input(struct device *dev,
				     const char *name,
						 const char *parent_name)
				     unsigned int clkid)
{
	struct clk_hw *hw;
	struct clk_init_data init;
	char *clk_name;
	int ret;

	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
	if (!hw)
		return ERR_PTR(-ENOMEM);
	struct clk_hw *hw;
	int err = 0;

	clk_name = kasprintf(GFP_KERNEL, "axg_%s", name);
	if (!clk_name)
		return ERR_PTR(-ENOMEM);

	init.name = clk_name;
	init.ops = &axg_clk_no_ops;
	init.flags = 0;
	init.parent_names = parent_name ? &parent_name : NULL;
	init.num_parents = parent_name ? 1 : 0;
	hw->init = &init;

	ret = devm_clk_hw_register(dev, hw);
	kfree(clk_name);

	return ret ? ERR_PTR(ret) : hw;
}

static int axg_register_clk_hw_input(struct device *dev,
				     const char *name,
				     unsigned int clkid)
{
	struct clk *parent_clk = devm_clk_get(dev, name);
	struct clk_hw *hw = NULL;

	if (IS_ERR(parent_clk)) {
		int err = PTR_ERR(parent_clk);
		return -ENOMEM;

	hw = meson_clk_hw_register_input(dev, name, clk_name, 0);
	if (IS_ERR(hw)) {
		/* It is ok if an input clock is missing */
		if (err == -ENOENT) {
		if (PTR_ERR(hw) == -ENOENT) {
			dev_dbg(dev, "%s not provided", name);
		} else {
			err = PTR_ERR(hw);
			if (err != -EPROBE_DEFER)
				dev_err(dev, "failed to get %s clock", name);
			return err;
		}
	} else {
		hw = axg_clk_hw_register_bypass(dev, name,
						__clk_get_name(parent_clk));
	}

	if (IS_ERR(hw)) {
		dev_err(dev, "failed to register %s clock", name);
		return PTR_ERR(hw);
		axg_audio_hw_onecell_data.hws[clkid] = hw;
	}

	axg_audio_hw_onecell_data.hws[clkid] = hw;
	return 0;
	kfree(clk_name);
	return err;
}

static int axg_register_clk_hw_inputs(struct device *dev,
@@ -759,7 +726,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
	struct regmap *map;
	struct resource *res;
	void __iomem *regs;
	struct clk *clk;
	struct clk_hw *hw;
	int ret, i;

@@ -775,9 +741,9 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
	}

	/* Get the mandatory peripheral clock */
	clk = devm_clk_get_enable(dev, "pclk");
	if (IS_ERR(clk))
		return PTR_ERR(clk);
	ret = devm_clk_get_enable(dev, "pclk");
	if (ret)
		return ret;

	ret = device_reset(dev);
	if (ret) {
@@ -786,8 +752,7 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
	}

	/* Register the peripheral input clock */
	hw = axg_clk_hw_register_bypass(dev, "audio_pclk",
					__clk_get_name(clk));
	hw = meson_clk_hw_register_input(dev, "pclk", "axg_audio_pclk", 0);
	if (IS_ERR(hw))
		return PTR_ERR(hw);

+44 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
 * Copyright (c) 2018 BayLibre, SAS.
 * Author: Jerome Brunet <jbrunet@baylibre.com>
 */

#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include "clkc.h"

static const struct clk_ops meson_clk_no_ops = {};

struct clk_hw *meson_clk_hw_register_input(struct device *dev,
					   const char *of_name,
					   const char *clk_name,
					   unsigned long flags)
{
	struct clk *parent_clk = devm_clk_get(dev, of_name);
	struct clk_init_data init;
	const char *parent_name;
	struct clk_hw *hw;
	int ret;

	if (IS_ERR(parent_clk))
		return (struct clk_hw *)parent_clk;

	hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
	if (!hw)
		return ERR_PTR(-ENOMEM);

	parent_name = __clk_get_name(parent_clk);
	init.name = clk_name;
	init.ops = &meson_clk_no_ops;
	init.flags = flags;
	init.parent_names = &parent_name;
	init.num_parents = 1;
	hw->init = &init;

	ret = devm_clk_hw_register(dev, hw);

	return ret ? ERR_PTR(ret) : hw;
}
EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);
+5 −0
Original line number Diff line number Diff line
@@ -119,4 +119,9 @@ extern const struct clk_ops meson_clk_mpll_ops;
extern const struct clk_ops meson_clk_phase_ops;
extern const struct clk_ops meson_vid_pll_div_ro_ops;

struct clk_hw *meson_clk_hw_register_input(struct device *dev,
					   const char *of_name,
					   const char *clk_name,
					   unsigned long flags);

#endif /* __CLKC_H */
+7 −1
Original line number Diff line number Diff line
@@ -216,10 +216,16 @@ static struct clk_regmap gxl_hdmi_pll_dco = {
			.shift   = 9,
			.width   = 5,
		},
		/*
		 * On gxl, there is a register shift due to
		 * HHI_HDMI_PLL_CNTL1 which does not exist on gxbb,
		 * so we use the HHI_HDMI_PLL_CNTL2 define from GXBB
		 * instead which is defined at the same offset.
		 */
		.frac = {
			.reg_off = HHI_HDMI_PLL_CNTL2,
			.shift   = 0,
			.width   = 12,
			.width   = 10,
		},
		.l = {
			.reg_off = HHI_HDMI_PLL_CNTL,
Loading