Commit 90f96477 authored by Billy Tsai's avatar Billy Tsai Committed by Jonathan Cameron
Browse files

iio: adc: aspeed: Fix the calculate error of clock.



The ADC clock formula is
ast2400/2500:
ADC clock period = PCLK * 2 * (ADC0C[31:17] + 1) * (ADC0C[9:0] + 1)
ast2600:
ADC clock period = PCLK * 2 * (ADC0C[15:0] + 1)
They all have one fixed divided 2 and the legacy driver didn't handle it.
This patch register the fixed factory clock device as the parent of ADC
clock scaler to fix this issue.

Signed-off-by: default avatarBilly Tsai <billy_tsai@aspeedtech.com>
Link: https://lore.kernel.org/r/20210922081520.30580-8-billy_tsai@aspeedtech.com


Signed-off-by: default avatarJonathan Cameron <Jonathan.Cameron@huawei.com>
parent 1b5ceb55
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -4,6 +4,12 @@
 *
 * Copyright (C) 2017 Google, Inc.
 * Copyright (C) 2021 Aspeed Technology Inc.
 *
 * ADC clock formula:
 * Ast2400/Ast2500:
 * clock period = period of PCLK * 2 * (ADC0C[31:17] + 1) * (ADC0C[9:0] + 1)
 * Ast2600:
 * clock period = period of PCLK * 2 * (ADC0C[15:0] + 1)
 */

#include <linux/clk.h>
@@ -85,6 +91,7 @@ struct aspeed_adc_data {
	struct regulator	*regulator;
	void __iomem		*base;
	spinlock_t		clk_lock;
	struct clk_hw		*fixed_div_clk;
	struct clk_hw		*clk_prescaler;
	struct clk_hw		*clk_scaler;
	struct reset_control	*rst;
@@ -197,6 +204,13 @@ static const struct iio_info aspeed_adc_iio_info = {
	.debugfs_reg_access = aspeed_adc_reg_access,
};

static void aspeed_adc_unregister_fixed_divider(void *data)
{
	struct clk_hw *clk = data;

	clk_hw_unregister_fixed_factor(clk);
}

static void aspeed_adc_reset_assert(void *data)
{
	struct reset_control *rst = data;
@@ -320,6 +334,19 @@ static int aspeed_adc_probe(struct platform_device *pdev)
	spin_lock_init(&data->clk_lock);
	snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name), "%s",
		 of_clk_get_parent_name(pdev->dev.of_node, 0));
	snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-fixed-div",
		 data->model_data->model_name);
	data->fixed_div_clk = clk_hw_register_fixed_factor(
		&pdev->dev, clk_name, clk_parent_name, 0, 1, 2);
	if (IS_ERR(data->fixed_div_clk))
		return PTR_ERR(data->fixed_div_clk);

	ret = devm_add_action_or_reset(data->dev,
				       aspeed_adc_unregister_fixed_divider,
				       data->fixed_div_clk);
	if (ret)
		return ret;
	snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name), clk_name);

	if (data->model_data->need_prescaler) {
		snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-prescaler",