Skip to content

Commit

Permalink
iio: adc: aspeed: Add func to set sampling rate.
Browse files Browse the repository at this point in the history
Add the function to set the sampling rate and keep the sampling period
for a driver used to wait the fresh value.
In addition, since the ADC clock is required when initializing the ADC
device, move clk_prepare_enable ahead of the initialization phase.

Signed-off-by: Billy Tsai <billy_tsai@aspeedtech.com>
Link: https://lore.kernel.org/r/20210922081520.30580-9-billy_tsai@aspeedtech.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
  • Loading branch information
Billy Tsai authored and Jonathan Cameron committed Oct 19, 2021
1 parent 90f9647 commit 13d4f9d
Showing 1 changed file with 39 additions and 19 deletions.
58 changes: 39 additions & 19 deletions drivers/iio/adc/aspeed_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@

#define ASPEED_ADC_INIT_POLLING_TIME 500
#define ASPEED_ADC_INIT_TIMEOUT 500000
/*
* When the sampling rate is too high, the ADC may not have enough charging
* time, resulting in a low voltage value. Thus, the default uses a slow
* sampling rate for most use cases.
*/
#define ASPEED_ADC_DEF_SAMPLING_RATE 65000

struct aspeed_adc_model_data {
const char *model_name;
Expand All @@ -96,6 +102,7 @@ struct aspeed_adc_data {
struct clk_hw *clk_scaler;
struct reset_control *rst;
int vref_mv;
u32 sample_period_ns;
};

#define ASPEED_CHAN(_idx, _data_reg_addr) { \
Expand Down Expand Up @@ -127,6 +134,24 @@ static const struct iio_chan_spec aspeed_adc_iio_channels[] = {
ASPEED_CHAN(15, 0x2E),
};

static int aspeed_adc_set_sampling_rate(struct iio_dev *indio_dev, u32 rate)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);

if (rate < data->model_data->min_sampling_rate ||
rate > data->model_data->max_sampling_rate)
return -EINVAL;
/* Each sampling needs 12 clocks to convert.*/
clk_set_rate(data->clk_scaler->clk, rate * ASPEED_CLOCKS_PER_SAMPLE);
rate = clk_get_rate(data->clk_scaler->clk);
data->sample_period_ns = DIV_ROUND_UP_ULL(
(u64)NSEC_PER_SEC * ASPEED_CLOCKS_PER_SAMPLE, rate);
dev_dbg(data->dev, "Adc clock = %d sample period = %d ns", rate,
data->sample_period_ns);

return 0;
}

static int aspeed_adc_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long mask)
Expand Down Expand Up @@ -157,17 +182,9 @@ static int aspeed_adc_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct aspeed_adc_data *data = iio_priv(indio_dev);

switch (mask) {
case IIO_CHAN_INFO_SAMP_FREQ:
if (val < data->model_data->min_sampling_rate ||
val > data->model_data->max_sampling_rate)
return -EINVAL;

clk_set_rate(data->clk_scaler->clk,
val * ASPEED_CLOCKS_PER_SAMPLE);
return 0;
return aspeed_adc_set_sampling_rate(indio_dev, val);

case IIO_CHAN_INFO_SCALE:
case IIO_CHAN_INFO_RAW:
Expand Down Expand Up @@ -391,6 +408,19 @@ static int aspeed_adc_probe(struct platform_device *pdev)
if (ret)
return ret;

ret = clk_prepare_enable(data->clk_scaler->clk);
if (ret)
return ret;
ret = devm_add_action_or_reset(data->dev,
aspeed_adc_clk_disable_unprepare,
data->clk_scaler->clk);
if (ret)
return ret;
ret = aspeed_adc_set_sampling_rate(indio_dev,
ASPEED_ADC_DEF_SAMPLING_RATE);
if (ret)
return ret;

adc_engine_control_reg_val =
readl(data->base + ASPEED_REG_ENGINE_CONTROL);
adc_engine_control_reg_val |=
Expand All @@ -417,16 +447,6 @@ static int aspeed_adc_probe(struct platform_device *pdev)
return ret;
}

ret = clk_prepare_enable(data->clk_scaler->clk);
if (ret)
return ret;

ret = devm_add_action_or_reset(data->dev,
aspeed_adc_clk_disable_unprepare,
data->clk_scaler->clk);
if (ret)
return ret;

/* Start all channels in normal mode. */
adc_engine_control_reg_val =
readl(data->base + ASPEED_REG_ENGINE_CONTROL);
Expand Down

0 comments on commit 13d4f9d

Please sign in to comment.