mirror of https://gitee.com/openkylin/linux.git
iio: adc: at91_adc: rework resolution selection
Move the possible resolution values back to the driver. This removes the atmel,adc-res and atmel,adc-res-names properties, leaving only atmel,adc-use-res. As atmel,adc-res-names had to contain "lowres" and "highres", those where already the only allowed values for atmel,adc-use-res. Also introduce a new compatible string for the sama5d3 as this is the only one with a different resolution. Also it doesn't even have the LOWRES bit. Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Reviewed-by: Ludovic Desroches <ludovic.desroches@microchip.com> Link: https://lore.kernel.org/r/20201128222818.1910764-3-alexandre.belloni@bootlin.com Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
parent
197cefcdc8
commit
5eb39ef81a
|
@ -204,6 +204,9 @@ struct at91_adc_caps {
|
||||||
u32 (*calc_startup_ticks)(u32 startup_time, u32 adc_clk_khz);
|
u32 (*calc_startup_ticks)(u32 startup_time, u32 adc_clk_khz);
|
||||||
|
|
||||||
u8 num_channels;
|
u8 num_channels;
|
||||||
|
|
||||||
|
u8 low_res_bits;
|
||||||
|
u8 high_res_bits;
|
||||||
struct at91_adc_reg_desc registers;
|
struct at91_adc_reg_desc registers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,7 +232,6 @@ struct at91_adc_state {
|
||||||
bool use_external;
|
bool use_external;
|
||||||
u32 vref_mv;
|
u32 vref_mv;
|
||||||
u32 res; /* resolution used for convertions */
|
u32 res; /* resolution used for convertions */
|
||||||
bool low_res; /* the resolution corresponds to the lowest one */
|
|
||||||
wait_queue_head_t wq_data_avail;
|
wait_queue_head_t wq_data_avail;
|
||||||
const struct at91_adc_caps *caps;
|
const struct at91_adc_caps *caps;
|
||||||
|
|
||||||
|
@ -754,58 +756,6 @@ static int at91_adc_read_raw(struct iio_dev *idev,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int at91_adc_of_get_resolution(struct iio_dev *idev,
|
|
||||||
struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
struct at91_adc_state *st = iio_priv(idev);
|
|
||||||
struct device_node *np = pdev->dev.of_node;
|
|
||||||
int count, i, ret = 0;
|
|
||||||
char *res_name, *s;
|
|
||||||
u32 *resolutions;
|
|
||||||
|
|
||||||
count = of_property_count_strings(np, "atmel,adc-res-names");
|
|
||||||
if (count < 2) {
|
|
||||||
dev_err(&idev->dev, "You must specified at least two resolution names for "
|
|
||||||
"adc-res-names property in the DT\n");
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
resolutions = kmalloc_array(count, sizeof(*resolutions), GFP_KERNEL);
|
|
||||||
if (!resolutions)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) {
|
|
||||||
dev_err(&idev->dev, "Missing adc-res property in the DT.\n");
|
|
||||||
ret = -ENODEV;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name))
|
|
||||||
res_name = "highres";
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (strcmp(res_name, s))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
st->res = resolutions[i];
|
|
||||||
if (!strcmp(res_name, "lowres"))
|
|
||||||
st->low_res = true;
|
|
||||||
else
|
|
||||||
st->low_res = false;
|
|
||||||
|
|
||||||
dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_err(&idev->dev, "There is no resolution for %s\n", res_name);
|
|
||||||
|
|
||||||
ret:
|
|
||||||
kfree(resolutions);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 calc_startup_ticks_9260(u32 startup_time, u32 adc_clk_khz)
|
static u32 calc_startup_ticks_9260(u32 startup_time, u32 adc_clk_khz)
|
||||||
{
|
{
|
||||||
|
@ -889,6 +839,7 @@ static int at91_adc_probe_dt(struct iio_dev *idev,
|
||||||
struct device_node *trig_node;
|
struct device_node *trig_node;
|
||||||
int i = 0, ret;
|
int i = 0, ret;
|
||||||
u32 prop;
|
u32 prop;
|
||||||
|
char *s;
|
||||||
|
|
||||||
st->caps = of_device_get_match_data(&pdev->dev);
|
st->caps = of_device_get_match_data(&pdev->dev);
|
||||||
|
|
||||||
|
@ -921,9 +872,13 @@ static int at91_adc_probe_dt(struct iio_dev *idev,
|
||||||
}
|
}
|
||||||
st->vref_mv = prop;
|
st->vref_mv = prop;
|
||||||
|
|
||||||
ret = at91_adc_of_get_resolution(idev, pdev);
|
st->res = st->caps->high_res_bits;
|
||||||
if (ret)
|
if (st->caps->low_res_bits &&
|
||||||
goto error_ret;
|
!of_property_read_string(node, "atmel,adc-use-res", (const char **)&s)
|
||||||
|
&& !strcmp(s, "lowres"))
|
||||||
|
st->res = st->caps->low_res_bits;
|
||||||
|
|
||||||
|
dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
|
||||||
|
|
||||||
st->registers = &st->caps->registers;
|
st->registers = &st->caps->registers;
|
||||||
st->num_channels = st->caps->num_channels;
|
st->num_channels = st->caps->num_channels;
|
||||||
|
@ -1245,7 +1200,7 @@ static int at91_adc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask;
|
reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask;
|
||||||
reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask;
|
reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask;
|
||||||
if (st->low_res)
|
if (st->res == st->caps->low_res_bits)
|
||||||
reg |= AT91_ADC_LOWRES;
|
reg |= AT91_ADC_LOWRES;
|
||||||
if (st->sleep_mode)
|
if (st->sleep_mode)
|
||||||
reg |= AT91_ADC_SLEEP;
|
reg |= AT91_ADC_SLEEP;
|
||||||
|
@ -1360,6 +1315,8 @@ static SIMPLE_DEV_PM_OPS(at91_adc_pm_ops, at91_adc_suspend, at91_adc_resume);
|
||||||
static struct at91_adc_caps at91sam9260_caps = {
|
static struct at91_adc_caps at91sam9260_caps = {
|
||||||
.calc_startup_ticks = calc_startup_ticks_9260,
|
.calc_startup_ticks = calc_startup_ticks_9260,
|
||||||
.num_channels = 4,
|
.num_channels = 4,
|
||||||
|
.low_res_bits = 8,
|
||||||
|
.high_res_bits = 10,
|
||||||
.registers = {
|
.registers = {
|
||||||
.channel_base = AT91_ADC_CHR(0),
|
.channel_base = AT91_ADC_CHR(0),
|
||||||
.drdy_mask = AT91_ADC_DRDY,
|
.drdy_mask = AT91_ADC_DRDY,
|
||||||
|
@ -1374,6 +1331,8 @@ static struct at91_adc_caps at91sam9rl_caps = {
|
||||||
.has_ts = true,
|
.has_ts = true,
|
||||||
.calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */
|
.calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */
|
||||||
.num_channels = 6,
|
.num_channels = 6,
|
||||||
|
.low_res_bits = 8,
|
||||||
|
.high_res_bits = 10,
|
||||||
.registers = {
|
.registers = {
|
||||||
.channel_base = AT91_ADC_CHR(0),
|
.channel_base = AT91_ADC_CHR(0),
|
||||||
.drdy_mask = AT91_ADC_DRDY,
|
.drdy_mask = AT91_ADC_DRDY,
|
||||||
|
@ -1388,6 +1347,8 @@ static struct at91_adc_caps at91sam9g45_caps = {
|
||||||
.has_ts = true,
|
.has_ts = true,
|
||||||
.calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */
|
.calc_startup_ticks = calc_startup_ticks_9260, /* same as 9260 */
|
||||||
.num_channels = 8,
|
.num_channels = 8,
|
||||||
|
.low_res_bits = 8,
|
||||||
|
.high_res_bits = 10,
|
||||||
.registers = {
|
.registers = {
|
||||||
.channel_base = AT91_ADC_CHR(0),
|
.channel_base = AT91_ADC_CHR(0),
|
||||||
.drdy_mask = AT91_ADC_DRDY,
|
.drdy_mask = AT91_ADC_DRDY,
|
||||||
|
@ -1405,6 +1366,8 @@ static struct at91_adc_caps at91sam9x5_caps = {
|
||||||
.ts_pen_detect_sensitivity = 2,
|
.ts_pen_detect_sensitivity = 2,
|
||||||
.calc_startup_ticks = calc_startup_ticks_9x5,
|
.calc_startup_ticks = calc_startup_ticks_9x5,
|
||||||
.num_channels = 12,
|
.num_channels = 12,
|
||||||
|
.low_res_bits = 8,
|
||||||
|
.high_res_bits = 10,
|
||||||
.registers = {
|
.registers = {
|
||||||
.channel_base = AT91_ADC_CDR0_9X5,
|
.channel_base = AT91_ADC_CDR0_9X5,
|
||||||
.drdy_mask = AT91_ADC_SR_DRDY_9X5,
|
.drdy_mask = AT91_ADC_SR_DRDY_9X5,
|
||||||
|
@ -1416,11 +1379,31 @@ static struct at91_adc_caps at91sam9x5_caps = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct at91_adc_caps sama5d3_caps = {
|
||||||
|
.has_ts = true,
|
||||||
|
.has_tsmr = true,
|
||||||
|
.ts_filter_average = 3,
|
||||||
|
.ts_pen_detect_sensitivity = 2,
|
||||||
|
.calc_startup_ticks = calc_startup_ticks_9x5,
|
||||||
|
.num_channels = 12,
|
||||||
|
.low_res_bits = 0,
|
||||||
|
.high_res_bits = 12,
|
||||||
|
.registers = {
|
||||||
|
.channel_base = AT91_ADC_CDR0_9X5,
|
||||||
|
.drdy_mask = AT91_ADC_SR_DRDY_9X5,
|
||||||
|
.status_register = AT91_ADC_SR_9X5,
|
||||||
|
.trigger_register = AT91_ADC_TRGR_9X5,
|
||||||
|
.mr_prescal_mask = AT91_ADC_PRESCAL_9G45,
|
||||||
|
.mr_startup_mask = AT91_ADC_STARTUP_9X5,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id at91_adc_dt_ids[] = {
|
static const struct of_device_id at91_adc_dt_ids[] = {
|
||||||
{ .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps },
|
{ .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps },
|
||||||
{ .compatible = "atmel,at91sam9rl-adc", .data = &at91sam9rl_caps },
|
{ .compatible = "atmel,at91sam9rl-adc", .data = &at91sam9rl_caps },
|
||||||
{ .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps },
|
{ .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps },
|
||||||
{ .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps },
|
{ .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps },
|
||||||
|
{ .compatible = "atmel,sama5d3-adc", .data = &sama5d3_caps },
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
|
MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
|
||||||
|
|
Loading…
Reference in New Issue