Commit 1ecbc2b3 authored by Bjorn Andersson's avatar Bjorn Andersson
Browse files

Merge tag '20220608105238.2973600-1-dmitry.baryshkov@linaro.org' into clk-for-5.20

v5.19-rc1 +
20220608105238.2973600-2-dmitry.baryshkov@linaro.org +
20220608105238.2973600-3-dmitry.baryshkov@linaro.org +
20220608105238.2973600-4-dmitry.baryshkov@linaro.org
parents e7c65912 553d12b2
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ clk-qcom-y += clk-branch.o
clk-qcom-y += clk-regmap-divider.o
clk-qcom-y += clk-regmap-mux.o
clk-qcom-y += clk-regmap-mux-div.o
clk-qcom-y += clk-regmap-phy-mux.o
clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-krait.o
clk-qcom-y += clk-hfpll.o
clk-qcom-y += reset.o
+62 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2022, Linaro Ltd.
 */

#include <linux/clk-provider.h>
#include <linux/bitfield.h>
#include <linux/regmap.h>
#include <linux/export.h>

#include "clk-regmap.h"
#include "clk-regmap-phy-mux.h"

#define PHY_MUX_MASK		GENMASK(1, 0)
#define PHY_MUX_PHY_SRC		0
#define PHY_MUX_REF_SRC		2

static inline struct clk_regmap_phy_mux *to_clk_regmap_phy_mux(struct clk_regmap *clkr)
{
	return container_of(clkr, struct clk_regmap_phy_mux, clkr);
}

static int phy_mux_is_enabled(struct clk_hw *hw)
{
	struct clk_regmap *clkr = to_clk_regmap(hw);
	struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);
	unsigned int val;

	regmap_read(clkr->regmap, phy_mux->reg, &val);
	val = FIELD_GET(PHY_MUX_MASK, val);

	WARN_ON(val != PHY_MUX_PHY_SRC && val != PHY_MUX_REF_SRC);

	return val == PHY_MUX_PHY_SRC;
}

static int phy_mux_enable(struct clk_hw *hw)
{
	struct clk_regmap *clkr = to_clk_regmap(hw);
	struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);

	return regmap_update_bits(clkr->regmap, phy_mux->reg,
				  PHY_MUX_MASK,
				  FIELD_PREP(PHY_MUX_MASK, PHY_MUX_PHY_SRC));
}

static void phy_mux_disable(struct clk_hw *hw)
{
	struct clk_regmap *clkr = to_clk_regmap(hw);
	struct clk_regmap_phy_mux *phy_mux = to_clk_regmap_phy_mux(clkr);

	regmap_update_bits(clkr->regmap, phy_mux->reg,
			   PHY_MUX_MASK,
			   FIELD_PREP(PHY_MUX_MASK, PHY_MUX_REF_SRC));
}

const struct clk_ops clk_regmap_phy_mux_ops = {
	.enable = phy_mux_enable,
	.disable = phy_mux_disable,
	.is_enabled = phy_mux_is_enabled,
};
EXPORT_SYMBOL_GPL(clk_regmap_phy_mux_ops);
+33 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2022, Linaro Ltd.
 */

#ifndef __QCOM_CLK_REGMAP_PHY_MUX_H__
#define __QCOM_CLK_REGMAP_PHY_MUX_H__

#include "clk-regmap.h"

/*
 * A clock implementation for PHY pipe and symbols clock muxes.
 *
 * If the clock is running off the from-PHY source, report it as enabled.
 * Report it as disabled otherwise (if it uses reference source).
 *
 * This way the PHY will disable the pipe clock before turning off the GDSC,
 * which in turn would lead to disabling corresponding pipe_clk_src (and thus
 * it being parked to a safe, reference clock source). And vice versa, after
 * enabling the GDSC the PHY will enable the pipe clock, which would cause
 * pipe_clk_src to be switched from a safe source to the working one.
 *
 * For some platforms this should be used for the UFS symbol_clk_src clocks
 * too.
 */
struct clk_regmap_phy_mux {
	u32			reg;
	struct clk_regmap	clkr;
};

extern const struct clk_ops clk_regmap_phy_mux_ops;

#endif
+15 −34
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "clk-rcg.h"
#include "clk-regmap-divider.h"
#include "clk-regmap-mux.h"
#include "clk-regmap-phy-mux.h"
#include "common.h"
#include "gdsc.h"
#include "reset.h"
@@ -255,26 +256,6 @@ static const struct clk_parent_data gcc_parent_data_5[] = {
	{ .hw = &gcc_gpll0_out_even.clkr.hw },
};

static const struct parent_map gcc_parent_map_6[] = {
	{ P_PCIE_0_PIPE_CLK, 0 },
	{ P_BI_TCXO, 2 },
};

static const struct clk_parent_data gcc_parent_data_6[] = {
	{ .fw_name = "pcie_0_pipe_clk", .name = "pcie_0_pipe_clk" },
	{ .fw_name = "bi_tcxo" },
};

static const struct parent_map gcc_parent_map_7[] = {
	{ P_PCIE_1_PIPE_CLK, 0 },
	{ P_BI_TCXO, 2 },
};

static const struct clk_parent_data gcc_parent_data_7[] = {
	{ .fw_name = "pcie_1_pipe_clk", .name = "pcie_1_pipe_clk" },
	{ .fw_name = "bi_tcxo" },
};

static const struct parent_map gcc_parent_map_8[] = {
	{ P_BI_TCXO, 0 },
	{ P_GCC_GPLL0_OUT_MAIN, 1 },
@@ -369,32 +350,32 @@ static const struct clk_parent_data gcc_parent_data_15[] = {
	{ .hw = &gcc_mss_gpll0_main_div_clk_src.clkr.hw },
};

static struct clk_regmap_mux gcc_pcie_0_pipe_clk_src = {
static struct clk_regmap_phy_mux gcc_pcie_0_pipe_clk_src = {
	.reg = 0x6b054,
	.shift = 0,
	.width = 2,
	.parent_map = gcc_parent_map_6,
	.clkr = {
		.hw.init = &(struct clk_init_data){
			.name = "gcc_pcie_0_pipe_clk_src",
			.parent_data = gcc_parent_data_6,
			.num_parents = ARRAY_SIZE(gcc_parent_data_6),
			.ops = &clk_regmap_mux_closest_ops,
			.parent_data = &(const struct clk_parent_data){
				.fw_name = "pcie_0_pipe_clk",
				.name = "pcie_0_pipe_clk",
			},
			.num_parents = 1,
			.ops = &clk_regmap_phy_mux_ops,
		},
	},
};

static struct clk_regmap_mux gcc_pcie_1_pipe_clk_src = {
static struct clk_regmap_phy_mux gcc_pcie_1_pipe_clk_src = {
	.reg = 0x8d054,
	.shift = 0,
	.width = 2,
	.parent_map = gcc_parent_map_7,
	.clkr = {
		.hw.init = &(struct clk_init_data){
			.name = "gcc_pcie_1_pipe_clk_src",
			.parent_data = gcc_parent_data_7,
			.num_parents = ARRAY_SIZE(gcc_parent_data_7),
			.ops = &clk_regmap_mux_closest_ops,
			.parent_data = &(const struct clk_parent_data){
				.fw_name = "pcie_1_pipe_clk",
				.name = "pcie_1_pipe_clk",
			},
			.num_parents = 1,
			.ops = &clk_regmap_phy_mux_ops,
		},
	},
};
+13 −36
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "clk-regmap.h"
#include "clk-regmap-divider.h"
#include "clk-regmap-mux.h"
#include "clk-regmap-phy-mux.h"
#include "gdsc.h"
#include "reset.h"

@@ -26,9 +27,7 @@ enum {
	P_GCC_GPLL0_OUT_MAIN,
	P_GCC_GPLL4_OUT_MAIN,
	P_GCC_GPLL9_OUT_MAIN,
	P_PCIE_0_PIPE_CLK,
	P_PCIE_1_PHY_AUX_CLK,
	P_PCIE_1_PIPE_CLK,
	P_SLEEP_CLK,
	P_UFS_PHY_RX_SYMBOL_0_CLK,
	P_UFS_PHY_RX_SYMBOL_1_CLK,
@@ -153,16 +152,6 @@ static const struct clk_parent_data gcc_parent_data_3[] = {
	{ .fw_name = "bi_tcxo" },
};

static const struct parent_map gcc_parent_map_4[] = {
	{ P_PCIE_0_PIPE_CLK, 0 },
	{ P_BI_TCXO, 2 },
};

static const struct clk_parent_data gcc_parent_data_4[] = {
	{ .fw_name = "pcie_0_pipe_clk", },
	{ .fw_name = "bi_tcxo", },
};

static const struct parent_map gcc_parent_map_5[] = {
	{ P_PCIE_1_PHY_AUX_CLK, 0 },
	{ P_BI_TCXO, 2 },
@@ -173,16 +162,6 @@ static const struct clk_parent_data gcc_parent_data_5[] = {
	{ .fw_name = "bi_tcxo" },
};

static const struct parent_map gcc_parent_map_6[] = {
	{ P_PCIE_1_PIPE_CLK, 0 },
	{ P_BI_TCXO, 2 },
};

static const struct clk_parent_data gcc_parent_data_6[] = {
	{ .fw_name = "pcie_1_pipe_clk" },
	{ .fw_name = "bi_tcxo" },
};

static const struct parent_map gcc_parent_map_7[] = {
	{ P_BI_TCXO, 0 },
	{ P_GCC_GPLL0_OUT_MAIN, 1 },
@@ -239,17 +218,16 @@ static const struct clk_parent_data gcc_parent_data_11[] = {
	{ .fw_name = "bi_tcxo" },
};

static struct clk_regmap_mux gcc_pcie_0_pipe_clk_src = {
static struct clk_regmap_phy_mux gcc_pcie_0_pipe_clk_src = {
	.reg = 0x7b060,
	.shift = 0,
	.width = 2,
	.parent_map = gcc_parent_map_4,
	.clkr = {
		.hw.init = &(struct clk_init_data){
			.name = "gcc_pcie_0_pipe_clk_src",
			.parent_data = gcc_parent_data_4,
			.num_parents = ARRAY_SIZE(gcc_parent_data_4),
			.ops = &clk_regmap_mux_closest_ops,
			.parent_data = &(const struct clk_parent_data){
				.fw_name = "pcie_0_pipe_clk",
			},
			.num_parents = 1,
			.ops = &clk_regmap_phy_mux_ops,
		},
	},
};
@@ -269,17 +247,16 @@ static struct clk_regmap_mux gcc_pcie_1_phy_aux_clk_src = {
	},
};

static struct clk_regmap_mux gcc_pcie_1_pipe_clk_src = {
static struct clk_regmap_phy_mux gcc_pcie_1_pipe_clk_src = {
	.reg = 0x9d064,
	.shift = 0,
	.width = 2,
	.parent_map = gcc_parent_map_6,
	.clkr = {
		.hw.init = &(struct clk_init_data){
			.name = "gcc_pcie_1_pipe_clk_src",
			.parent_data = gcc_parent_data_6,
			.num_parents = ARRAY_SIZE(gcc_parent_data_6),
			.ops = &clk_regmap_mux_closest_ops,
			.parent_data = &(const struct clk_parent_data){
				.fw_name = "pcie_1_pipe_clk",
			},
			.num_parents = 1,
			.ops = &clk_regmap_phy_mux_ops,
		},
	},
};