162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2017 Chen-Yu Tsai. All rights reserved.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef _CCU_SDM_H
762306a36Sopenharmony_ci#define _CCU_SDM_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/clk-provider.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include "ccu_common.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistruct ccu_sdm_setting {
1462306a36Sopenharmony_ci	unsigned long	rate;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	/*
1762306a36Sopenharmony_ci	 * XXX We don't know what the step and bottom register fields
1862306a36Sopenharmony_ci	 * mean. Just copy the whole register value from the vendor
1962306a36Sopenharmony_ci	 * kernel for now.
2062306a36Sopenharmony_ci	 */
2162306a36Sopenharmony_ci	u32		pattern;
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci	/*
2462306a36Sopenharmony_ci	 * M and N factors here should be the values used in
2562306a36Sopenharmony_ci	 * calculation, not the raw values written to registers
2662306a36Sopenharmony_ci	 */
2762306a36Sopenharmony_ci	u32		m;
2862306a36Sopenharmony_ci	u32		n;
2962306a36Sopenharmony_ci};
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistruct ccu_sdm_internal {
3262306a36Sopenharmony_ci	struct ccu_sdm_setting	*table;
3362306a36Sopenharmony_ci	u32		table_size;
3462306a36Sopenharmony_ci	/* early SoCs don't have the SDM enable bit in the PLL register */
3562306a36Sopenharmony_ci	u32		enable;
3662306a36Sopenharmony_ci	/* second enable bit in tuning register */
3762306a36Sopenharmony_ci	u32		tuning_enable;
3862306a36Sopenharmony_ci	u16		tuning_reg;
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci#define _SUNXI_CCU_SDM(_table, _enable,			\
4262306a36Sopenharmony_ci		       _reg, _reg_enable)		\
4362306a36Sopenharmony_ci	{						\
4462306a36Sopenharmony_ci		.table		= _table,		\
4562306a36Sopenharmony_ci		.table_size	= ARRAY_SIZE(_table),	\
4662306a36Sopenharmony_ci		.enable		= _enable,		\
4762306a36Sopenharmony_ci		.tuning_enable	= _reg_enable,		\
4862306a36Sopenharmony_ci		.tuning_reg	= _reg,			\
4962306a36Sopenharmony_ci	}
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cibool ccu_sdm_helper_is_enabled(struct ccu_common *common,
5262306a36Sopenharmony_ci			       struct ccu_sdm_internal *sdm);
5362306a36Sopenharmony_civoid ccu_sdm_helper_enable(struct ccu_common *common,
5462306a36Sopenharmony_ci			   struct ccu_sdm_internal *sdm,
5562306a36Sopenharmony_ci			   unsigned long rate);
5662306a36Sopenharmony_civoid ccu_sdm_helper_disable(struct ccu_common *common,
5762306a36Sopenharmony_ci			    struct ccu_sdm_internal *sdm);
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cibool ccu_sdm_helper_has_rate(struct ccu_common *common,
6062306a36Sopenharmony_ci			     struct ccu_sdm_internal *sdm,
6162306a36Sopenharmony_ci			     unsigned long rate);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciunsigned long ccu_sdm_helper_read_rate(struct ccu_common *common,
6462306a36Sopenharmony_ci				       struct ccu_sdm_internal *sdm,
6562306a36Sopenharmony_ci				       u32 m, u32 n);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciint ccu_sdm_helper_get_factors(struct ccu_common *common,
6862306a36Sopenharmony_ci			       struct ccu_sdm_internal *sdm,
6962306a36Sopenharmony_ci			       unsigned long rate,
7062306a36Sopenharmony_ci			       unsigned long *m, unsigned long *n);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#endif
73