summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Agner <stefan.agner@toradex.com>2015-01-16 17:14:39 +0100
committerStefan Agner <stefan.agner@toradex.com>2015-01-24 00:41:31 +0100
commit6a9e06500f5649c89ed8007c43444981f43fe9d4 (patch)
treee2f3b95fa0c8e0e36cf027c8c7a82b123126d00f
parent62a449d8992ec7b0c13cf3932a0040d26f6e0426 (diff)
iio: adc: vf610: calculate ADC clock dynamically
Add new ADC device tree properties to specify the ADC mode which should be used. According to the mode, the maximum specification of the ADC clock can be determined and hence the required divisor is calculated dynamically.
-rw-r--r--drivers/iio/adc/vf610_adc.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index a9e2a0156dfa..deffcc6658a4 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -128,6 +128,7 @@ struct vf610_adc_feature {
int res_mode;
bool lpm;
+ bool hsc;
bool calibration;
bool ovwren;
};
@@ -140,6 +141,9 @@ struct vf610_adc {
u32 vref_uv;
u32 value;
struct regulator *vref;
+ unsigned long max_clk_default;
+ unsigned long max_clk_high_speed;
+ unsigned long max_clk_low_power;
struct vf610_adc_feature adc_feature;
u32 sample_freq_avail[VF610_SAMPLE_FREQ_CNT];
@@ -187,19 +191,39 @@ static const struct iio_chan_spec vf610_adc_iio_channels[] = {
static inline void vf610_adc_cfg_init(struct vf610_adc *info,
struct device_node *node)
{
+ struct vf610_adc_feature *adc_feature = &info->adc_feature;
unsigned long adck_rate, ipg_rate = clk_get_rate(info->clk);
- int i;
+ u32 max_adck_rate[3];
+ int divisor, i;
/* set default Configuration for ADC controller */
- info->adc_feature.clk_sel = VF610_ADCIOC_BUSCLK_SET;
- info->adc_feature.vol_ref = VF610_ADCIOC_VR_VREF_SET;
-
- info->adc_feature.calibration = true;
- info->adc_feature.ovwren = true;
+ adc_feature->clk_sel = VF610_ADCIOC_BUSCLK_SET;
+ adc_feature->vol_ref = VF610_ADCIOC_VR_VREF_SET;
+
+ adc_feature->calibration = true;
+ adc_feature->ovwren = true;
+
+ adc_feature->res_mode = 12;
+ adc_feature->sample_rate = 1;
+ adc_feature->lpm = of_property_read_bool(node, "fsl,use-lpm");
+ adc_feature->hsc = of_property_read_bool(node, "fsl,use-hsc");
+
+ /* fall-back value using a conservative divisor */
+ adc_feature->clk_div = 4;
+
+ if (!of_property_read_u32_array(node, "fsl,adck-max-frequency",
+ max_adck_rate, 3)) {
+ /* calculate clk divider which is within specification */
+ if (adc_feature->lpm)
+ divisor = ipg_rate / max_adck_rate[2];
+ else if (adc_feature->hsc)
+ divisor = ipg_rate / max_adck_rate[1];
+ else
+ divisor = ipg_rate / max_adck_rate[0];
+
+ adc_feature->clk_div = 1 << fls(divisor + 1);
+ }
- info->adc_feature.clk_div = 1;
- info->adc_feature.res_mode = 12;
- info->adc_feature.sample_rate = 1;
info->adc_feature.lpm = true;
/*
* Calculate ADC sample frequencies