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: Billy Tsai <billy_tsai@aspeedtech.com> Link: https://lore.kernel.org/r/20210922081520.30580-8-billy_tsai@aspeedtech.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
1b5ceb55fe
commit
90f9647753
|
@ -4,6 +4,12 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2017 Google, Inc.
|
* Copyright (C) 2017 Google, Inc.
|
||||||
* Copyright (C) 2021 Aspeed Technology 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>
|
#include <linux/clk.h>
|
||||||
|
@ -85,6 +91,7 @@ struct aspeed_adc_data {
|
||||||
struct regulator *regulator;
|
struct regulator *regulator;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
spinlock_t clk_lock;
|
spinlock_t clk_lock;
|
||||||
|
struct clk_hw *fixed_div_clk;
|
||||||
struct clk_hw *clk_prescaler;
|
struct clk_hw *clk_prescaler;
|
||||||
struct clk_hw *clk_scaler;
|
struct clk_hw *clk_scaler;
|
||||||
struct reset_control *rst;
|
struct reset_control *rst;
|
||||||
|
@ -197,6 +204,13 @@ static const struct iio_info aspeed_adc_iio_info = {
|
||||||
.debugfs_reg_access = aspeed_adc_reg_access,
|
.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)
|
static void aspeed_adc_reset_assert(void *data)
|
||||||
{
|
{
|
||||||
struct reset_control *rst = 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);
|
spin_lock_init(&data->clk_lock);
|
||||||
snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name), "%s",
|
snprintf(clk_parent_name, ARRAY_SIZE(clk_parent_name), "%s",
|
||||||
of_clk_get_parent_name(pdev->dev.of_node, 0));
|
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) {
|
if (data->model_data->need_prescaler) {
|
||||||
snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-prescaler",
|
snprintf(clk_name, ARRAY_SIZE(clk_name), "%s-prescaler",
|
||||||
|
|
Loading…
Reference in New Issue