162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/* Copyright (c) 2013, The Linux Foundation. All rights reserved. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#ifndef __QCOM_CLK_BRANCH_H__
562306a36Sopenharmony_ci#define __QCOM_CLK_BRANCH_H__
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/bitfield.h>
862306a36Sopenharmony_ci#include <linux/clk-provider.h>
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "clk-regmap.h"
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/**
1362306a36Sopenharmony_ci * struct clk_branch - gating clock with status bit and dynamic hardware gating
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * @hwcg_reg: dynamic hardware clock gating register
1662306a36Sopenharmony_ci * @hwcg_bit: ORed with @hwcg_reg to enable dynamic hardware clock gating
1762306a36Sopenharmony_ci * @halt_reg: halt register
1862306a36Sopenharmony_ci * @halt_bit: ANDed with @halt_reg to test for clock halted
1962306a36Sopenharmony_ci * @halt_check: type of halt checking to perform
2062306a36Sopenharmony_ci * @clkr: handle between common and hardware-specific interfaces
2162306a36Sopenharmony_ci *
2262306a36Sopenharmony_ci * Clock which can gate its output.
2362306a36Sopenharmony_ci */
2462306a36Sopenharmony_cistruct clk_branch {
2562306a36Sopenharmony_ci	u32	hwcg_reg;
2662306a36Sopenharmony_ci	u32	halt_reg;
2762306a36Sopenharmony_ci	u8	hwcg_bit;
2862306a36Sopenharmony_ci	u8	halt_bit;
2962306a36Sopenharmony_ci	u8	halt_check;
3062306a36Sopenharmony_ci#define BRANCH_VOTED			BIT(7) /* Delay on disable */
3162306a36Sopenharmony_ci#define BRANCH_HALT			0 /* pol: 1 = halt */
3262306a36Sopenharmony_ci#define BRANCH_HALT_VOTED		(BRANCH_HALT | BRANCH_VOTED)
3362306a36Sopenharmony_ci#define BRANCH_HALT_ENABLE		1 /* pol: 0 = halt */
3462306a36Sopenharmony_ci#define BRANCH_HALT_ENABLE_VOTED	(BRANCH_HALT_ENABLE | BRANCH_VOTED)
3562306a36Sopenharmony_ci#define BRANCH_HALT_DELAY		2 /* No bit to check; just delay */
3662306a36Sopenharmony_ci#define BRANCH_HALT_SKIP		3 /* Don't check halt bit */
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	struct clk_regmap clkr;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/* Branch clock common bits for HLOS-owned clocks */
4262306a36Sopenharmony_ci#define CBCR_CLK_OFF			BIT(31)
4362306a36Sopenharmony_ci#define CBCR_NOC_FSM_STATUS		GENMASK(30, 28)
4462306a36Sopenharmony_ci #define FSM_STATUS_ON			BIT(1)
4562306a36Sopenharmony_ci#define CBCR_FORCE_MEM_CORE_ON		BIT(14)
4662306a36Sopenharmony_ci#define CBCR_FORCE_MEM_PERIPH_ON	BIT(13)
4762306a36Sopenharmony_ci#define CBCR_FORCE_MEM_PERIPH_OFF	BIT(12)
4862306a36Sopenharmony_ci#define CBCR_WAKEUP			GENMASK(11, 8)
4962306a36Sopenharmony_ci#define CBCR_SLEEP			GENMASK(7, 4)
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic inline void qcom_branch_set_force_mem_core(struct regmap *regmap,
5262306a36Sopenharmony_ci						  struct clk_branch clk, bool on)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	regmap_update_bits(regmap, clk.halt_reg, CBCR_FORCE_MEM_CORE_ON,
5562306a36Sopenharmony_ci			   on ? CBCR_FORCE_MEM_CORE_ON : 0);
5662306a36Sopenharmony_ci}
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_cistatic inline void qcom_branch_set_force_periph_on(struct regmap *regmap,
5962306a36Sopenharmony_ci						   struct clk_branch clk, bool on)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	regmap_update_bits(regmap, clk.halt_reg, CBCR_FORCE_MEM_PERIPH_ON,
6262306a36Sopenharmony_ci			   on ? CBCR_FORCE_MEM_PERIPH_ON : 0);
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic inline void qcom_branch_set_force_periph_off(struct regmap *regmap,
6662306a36Sopenharmony_ci						    struct clk_branch clk, bool on)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	regmap_update_bits(regmap, clk.halt_reg, CBCR_FORCE_MEM_PERIPH_OFF,
6962306a36Sopenharmony_ci			   on ? CBCR_FORCE_MEM_PERIPH_OFF : 0);
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic inline void qcom_branch_set_wakeup(struct regmap *regmap, struct clk_branch clk, u32 val)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	regmap_update_bits(regmap, clk.halt_reg, CBCR_WAKEUP,
7562306a36Sopenharmony_ci			   FIELD_PREP(CBCR_WAKEUP, val));
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic inline void qcom_branch_set_sleep(struct regmap *regmap, struct clk_branch clk, u32 val)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	regmap_update_bits(regmap, clk.halt_reg, CBCR_SLEEP,
8162306a36Sopenharmony_ci			   FIELD_PREP(CBCR_SLEEP, val));
8262306a36Sopenharmony_ci}
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ciextern const struct clk_ops clk_branch_ops;
8562306a36Sopenharmony_ciextern const struct clk_ops clk_branch2_ops;
8662306a36Sopenharmony_ciextern const struct clk_ops clk_branch_simple_ops;
8762306a36Sopenharmony_ciextern const struct clk_ops clk_branch2_aon_ops;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci#define to_clk_branch(_hw) \
9062306a36Sopenharmony_ci	container_of(to_clk_regmap(_hw), struct clk_branch, clkr)
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci#endif
93