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

Merge tag 'clk-meson-v6.13-1' of https://github.com/BayLibre/clk-meson into clk-amlogic

Pull Amlogic clk driver updates from Jerome Brunet:

 - Fix hifi_pll rate calculation on Amlogic s4 and c3
 - Move audio reset implementation from the Amlogic axg-audio clock
   controller driver to the reset directory, using the auxiliary device
   bus
 - Remove the unnecessary spinlock in the Amlogic mpll driver
 - Fix Amlogic meson8 clock controller DT bindings

* tag 'clk-meson-v6.13-1' of https://github.com/BayLibre/clk-meson:
  clk: amlogic: axg-audio: use the auxiliary reset driver
  reset: amlogic: Fix small whitespace issue
  reset: amlogic: add auxiliary reset driver support
  reset: amlogic: split the device core and platform probe
  reset: amlogic: move drivers to a dedicated directory
  reset: amlogic: add reset status support
  reset: amlogic: use reset number instead of register count
  reset: amlogic: add driver parameters
  reset: amlogic: make parameters unsigned
  reset: amlogic: use generic data matching function
  reset: amlogic: convert driver to regmap
  dt-bindings: clock: convert amlogic,meson8b-clkc.txt to dtschema
  clk: meson: meson8b: remove spinlock
  clk: meson: mpll: Delete a useless spinlock from the MPLL
  clk: meson: s4: pll: fix frac maximum value for hifi_pll
  clk: meson: c3: pll: fix frac maximum value for hifi_pll
  clk: meson: Support PLL with fixed fractional denominators
  clk: meson: s4: pll: hifi_pll support fractional multiplier
parents 9852d85e 664988eb
Loading
Loading
Loading
Loading
+45 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/amlogic,meson8-clkc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Amlogic Meson8, Meson8b and Meson8m2 Clock and Reset Controller

maintainers:
  - Neil Armstrong <neil.armstrong@linaro.org>

properties:
  compatible:
    oneOf:
      - enum:
          - amlogic,meson8-clkc
          - amlogic,meson8b-clkc
      - items:
          - const: amlogic,meson8m2-clkc
          - const: amlogic,meson8-clkc

  clocks:
    minItems: 2
    maxItems: 3

  clock-names:
    minItems: 2
    items:
      - const: xtal
      - const: ddr_pll
      - const: clk_32k

  '#clock-cells':
    const: 1

  '#reset-cells':
    const: 1

required:
  - compatible
  - clocks
  - clock-names
  - '#reset-cells'

additionalProperties: false
+0 −51
Original line number Diff line number Diff line
* Amlogic Meson8, Meson8b and Meson8m2 Clock and Reset Unit

The Amlogic Meson8 / Meson8b / Meson8m2 clock controller generates and
supplies clock to various controllers within the SoC.

Required Properties:

- compatible: must be one of:
	- "amlogic,meson8-clkc" for Meson8 (S802) SoCs
	- "amlogic,meson8b-clkc" for Meson8 (S805) SoCs
	- "amlogic,meson8m2-clkc" for Meson8m2 (S812) SoCs
- #clock-cells: should be 1.
- #reset-cells: should be 1.
- clocks: list of clock phandles, one for each entry in clock-names
- clock-names: should contain the following:
  * "xtal": the 24MHz system oscillator
  * "ddr_pll": the DDR PLL clock
  * "clk_32k": (if present) the 32kHz clock signal from GPIOAO_6 (CLK_32K_IN)

Parent node should have the following properties :
- compatible: "amlogic,meson-hhi-sysctrl", "simple-mfd", "syscon"
- reg: base address and size of the HHI system control register space.

Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
preprocessor macros in the dt-bindings/clock/meson8b-clkc.h header and can be
used in device tree sources.

Similarly a preprocessor macro for each reset line is defined in
dt-bindings/reset/amlogic,meson8b-clkc-reset.h (which can be used from the
device tree sources).


Example: Clock controller node:

	clkc: clock-controller {
		compatible = "amlogic,meson8b-clkc";
		#clock-cells = <1>;
		#reset-cells = <1>;
	};


Example: UART controller node that consumes the clock generated by the clock
  controller:

	uart_AO: serial@c81004c0 {
		compatible = "amlogic,meson-uart";
		reg = <0xc81004c0 0x14>;
		interrupts = <0 90 1>;
		clocks = <&clkc CLKID_CLK81>;
	};
+1 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ config COMMON_CLK_AXG_AUDIO
	select COMMON_CLK_MESON_SCLK_DIV
	select COMMON_CLK_MESON_CLKC_UTILS
	select REGMAP_MMIO
	imply RESET_MESON_AUX
	help
	  Support for the audio clock controller on AmLogic A113D devices,
	  aka axg, Say Y if you want audio subsystem to work.
+9 −100
Original line number Diff line number Diff line
@@ -15,6 +15,8 @@
#include <linux/reset-controller.h>
#include <linux/slab.h>

#include <soc/amlogic/reset-meson-aux.h>

#include "meson-clkc-utils.h"
#include "axg-audio.h"
#include "clk-regmap.h"
@@ -1678,84 +1680,6 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
	&sm1_earcrx_dmac_clk,
};

struct axg_audio_reset_data {
	struct reset_controller_dev rstc;
	struct regmap *map;
	unsigned int offset;
};

static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
					unsigned long id,
					unsigned int *reg,
					unsigned int *bit)
{
	unsigned int stride = regmap_get_reg_stride(rst->map);

	*reg = (id / (stride * BITS_PER_BYTE)) * stride;
	*reg += rst->offset;
	*bit = id % (stride * BITS_PER_BYTE);
}

static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
				unsigned long id, bool assert)
{
	struct axg_audio_reset_data *rst =
		container_of(rcdev, struct axg_audio_reset_data, rstc);
	unsigned int offset, bit;

	axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);

	regmap_update_bits(rst->map, offset, BIT(bit),
			assert ? BIT(bit) : 0);

	return 0;
}

static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	struct axg_audio_reset_data *rst =
		container_of(rcdev, struct axg_audio_reset_data, rstc);
	unsigned int val, offset, bit;

	axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);

	regmap_read(rst->map, offset, &val);

	return !!(val & BIT(bit));
}

static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	return axg_audio_reset_update(rcdev, id, true);
}

static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	return axg_audio_reset_update(rcdev, id, false);
}

static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
				unsigned long id)
{
	int ret;

	ret = axg_audio_reset_assert(rcdev, id);
	if (ret)
		return ret;

	return axg_audio_reset_deassert(rcdev, id);
}

static const struct reset_control_ops axg_audio_rstc_ops = {
	.assert = axg_audio_reset_assert,
	.deassert = axg_audio_reset_deassert,
	.reset = axg_audio_reset_toggle,
	.status = axg_audio_reset_status,
};

static struct regmap_config axg_audio_regmap_cfg = {
	.reg_bits	= 32,
	.val_bits	= 32,
@@ -1766,16 +1690,14 @@ struct audioclk_data {
	struct clk_regmap *const *regmap_clks;
	unsigned int regmap_clk_num;
	struct meson_clk_hw_data hw_clks;
	unsigned int reset_offset;
	unsigned int reset_num;
	unsigned int max_register;
	const char *rst_drvname;
};

static int axg_audio_clkc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	const struct audioclk_data *data;
	struct axg_audio_reset_data *rst;
	struct regmap *map;
	void __iomem *regs;
	struct clk_hw *hw;
@@ -1834,22 +1756,11 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
	if (ret)
		return ret;

	/* Stop here if there is no reset */
	if (!data->reset_num)
		return 0;

	rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
	if (!rst)
		return -ENOMEM;
	/* Register auxiliary reset driver when applicable */
	if (data->rst_drvname)
		ret = devm_meson_rst_aux_register(dev, map, data->rst_drvname);

	rst->map = map;
	rst->offset = data->reset_offset;
	rst->rstc.nr_resets = data->reset_num;
	rst->rstc.ops = &axg_audio_rstc_ops;
	rst->rstc.of_node = dev->of_node;
	rst->rstc.owner = THIS_MODULE;

	return devm_reset_controller_register(dev, &rst->rstc);
	return ret;
}

static const struct audioclk_data axg_audioclk_data = {
@@ -1869,9 +1780,8 @@ static const struct audioclk_data g12a_audioclk_data = {
		.hws = g12a_audio_hw_clks,
		.num = ARRAY_SIZE(g12a_audio_hw_clks),
	},
	.reset_offset = AUDIO_SW_RESET,
	.reset_num = 26,
	.max_register = AUDIO_CLK_SPDIFOUT_B_CTRL,
	.rst_drvname = "rst-g12a",
};

static const struct audioclk_data sm1_audioclk_data = {
@@ -1881,9 +1791,8 @@ static const struct audioclk_data sm1_audioclk_data = {
		.hws = sm1_audio_hw_clks,
		.num = ARRAY_SIZE(sm1_audio_hw_clks),
	},
	.reset_offset = AUDIO_SM1_SW_RESET0,
	.reset_num = 39,
	.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
	.rst_drvname = "rst-sm1",
};

static const struct of_device_id clkc_match_table[] = {
+0 −6
Original line number Diff line number Diff line
@@ -23,8 +23,6 @@

#include <dt-bindings/clock/axg-clkc.h>

static DEFINE_SPINLOCK(meson_clk_lock);

static struct clk_regmap axg_fixed_pll_dco = {
	.data = &(struct meson_clk_pll_data){
		.en = {
@@ -506,7 +504,6 @@ static struct clk_regmap axg_mpll0_div = {
			.shift   = 0,
			.width	 = 1,
		},
		.lock = &meson_clk_lock,
		.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
	},
	.hw.init = &(struct clk_init_data){
@@ -557,7 +554,6 @@ static struct clk_regmap axg_mpll1_div = {
			.shift   = 1,
			.width	 = 1,
		},
		.lock = &meson_clk_lock,
		.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
	},
	.hw.init = &(struct clk_init_data){
@@ -613,7 +609,6 @@ static struct clk_regmap axg_mpll2_div = {
			.shift   = 2,
			.width	 = 1,
		},
		.lock = &meson_clk_lock,
		.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
	},
	.hw.init = &(struct clk_init_data){
@@ -664,7 +659,6 @@ static struct clk_regmap axg_mpll3_div = {
			.shift   = 3,
			.width	 = 1,
		},
		.lock = &meson_clk_lock,
		.flags = CLK_MESON_MPLL_ROUND_CLOSEST,
	},
	.hw.init = &(struct clk_init_data){
Loading