iio: dac: ad3552r-hs: add support for internal ramp

The ad3552r can be feeded from the HDL controller by an internally
generated 16bit ramp, useful for debug pourposes. Add debugfs a file
to enable or disable it.

Signed-off-by: Angelo Dureghello <adureghello@baylibre.com>
Link: https://patch.msgid.link/20250409-wip-bl-ad3552r-fixes-v5-5-fb429c3a6515@baylibre.com
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
Angelo Dureghello
2025-04-09 20:36:32 +02:00
committed by Jonathan Cameron
parent ca74d0eb06
commit b1c5d68ea6

View File

@@ -7,6 +7,7 @@
*/
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/backend.h>
@@ -54,6 +55,18 @@ struct ad3552r_hs_state {
struct ad3552r_hs_platform_data *data;
/* INTERFACE_CONFIG_D register cache, in DDR we cannot read values. */
u32 config_d;
/* Protects backend I/O operations from concurrent accesses. */
struct mutex lock;
};
enum ad3552r_sources {
AD3552R_SRC_NORMAL,
AD3552R_SRC_RAMP_16BIT,
};
static const char * const dbgfs_attr_source[] = {
[AD3552R_SRC_NORMAL] = "normal",
[AD3552R_SRC_RAMP_16BIT] = "ramp-16bit",
};
static int ad3552r_hs_reg_read(struct ad3552r_hs_state *st, u32 reg, u32 *val,
@@ -65,6 +78,20 @@ static int ad3552r_hs_reg_read(struct ad3552r_hs_state *st, u32 reg, u32 *val,
return st->data->bus_reg_read(st->back, reg, val, xfer_size);
}
static int ad3552r_hs_set_data_source(struct ad3552r_hs_state *st,
enum iio_backend_data_source type)
{
int i, ret;
for (i = 0; i < st->model_data->num_hw_channels; ++i) {
ret = iio_backend_data_source_set(st->back, i, type);
if (ret)
return ret;
}
return 0;
}
static int ad3552r_hs_update_reg_bits(struct ad3552r_hs_state *st, u32 reg,
u32 mask, u32 val, size_t xfer_size)
{
@@ -483,6 +510,103 @@ static int ad3552r_hs_reg_access(struct iio_dev *indio_dev, unsigned int reg,
return st->data->bus_reg_write(st->back, reg, writeval, 1);
}
static ssize_t ad3552r_hs_show_data_source(struct file *f, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ad3552r_hs_state *st = file_inode(f)->i_private;
enum iio_backend_data_source type;
int idx, ret;
guard(mutex)(&st->lock);
ret = iio_backend_data_source_get(st->back, 0, &type);
if (ret)
return ret;
switch (type) {
case IIO_BACKEND_INTERNAL_RAMP_16BIT:
idx = AD3552R_SRC_RAMP_16BIT;
break;
case IIO_BACKEND_EXTERNAL:
idx = AD3552R_SRC_NORMAL;
break;
default:
return -EINVAL;
}
return simple_read_from_buffer(userbuf, count, ppos,
dbgfs_attr_source[idx],
strlen(dbgfs_attr_source[idx]));
}
static ssize_t ad3552r_hs_write_data_source(struct file *f,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
struct ad3552r_hs_state *st = file_inode(f)->i_private;
char buf[64];
int ret, source;
guard(mutex)(&st->lock);
ret = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, userbuf,
count);
if (ret < 0)
return ret;
buf[count] = '\0';
ret = match_string(dbgfs_attr_source, ARRAY_SIZE(dbgfs_attr_source),
buf);
if (ret < 0)
return ret;
switch (ret) {
case AD3552R_SRC_RAMP_16BIT:
source = IIO_BACKEND_INTERNAL_RAMP_16BIT;
break;
case AD3552R_SRC_NORMAL:
source = IIO_BACKEND_EXTERNAL;
break;
default:
return -EINVAL;
}
ret = ad3552r_hs_set_data_source(st, source);
if (ret)
return ret;
return count;
}
static ssize_t ad3552r_hs_show_data_source_avail(struct file *f,
char __user *userbuf,
size_t count, loff_t *ppos)
{
ssize_t len = 0;
char buf[128];
int i;
for (i = 0; i < ARRAY_SIZE(dbgfs_attr_source); i++) {
len += scnprintf(buf + len, PAGE_SIZE - len, "%s ",
dbgfs_attr_source[i]);
}
buf[len - 1] = '\n';
return simple_read_from_buffer(userbuf, count, ppos, buf, len);
}
static const struct file_operations ad3552r_hs_data_source_fops = {
.owner = THIS_MODULE,
.write = ad3552r_hs_write_data_source,
.read = ad3552r_hs_show_data_source,
};
static const struct file_operations ad3552r_hs_data_source_avail_fops = {
.owner = THIS_MODULE,
.read = ad3552r_hs_show_data_source_avail,
};
static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
{
u16 id;
@@ -550,11 +674,7 @@ static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
if (ret)
return ret;
ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
if (ret)
return ret;
ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
ret = ad3552r_hs_set_data_source(st, IIO_BACKEND_EXTERNAL);
if (ret)
return ret;
@@ -661,6 +781,26 @@ static const struct iio_info ad3552r_hs_info = {
.debugfs_reg_access = &ad3552r_hs_reg_access,
};
static void ad3552r_hs_debugfs_init(struct iio_dev *indio_dev)
{
struct ad3552r_hs_state *st = iio_priv(indio_dev);
struct dentry *d = iio_get_debugfs_dentry(indio_dev);
if (!IS_ENABLED(CONFIG_DEBUG_FS))
return;
d = iio_get_debugfs_dentry(indio_dev);
if (!d) {
dev_warn(st->dev, "can't set debugfs in driver dir\n");
return;
}
debugfs_create_file("data_source", 0600, d, st,
&ad3552r_hs_data_source_fops);
debugfs_create_file("data_source_available", 0600, d, st,
&ad3552r_hs_data_source_avail_fops);
}
static int ad3552r_hs_probe(struct platform_device *pdev)
{
struct ad3552r_hs_state *st;
@@ -705,7 +845,17 @@ static int ad3552r_hs_probe(struct platform_device *pdev)
if (ret)
return ret;
return devm_iio_device_register(&pdev->dev, indio_dev);
ret = devm_iio_device_register(&pdev->dev, indio_dev);
if (ret)
return ret;
ret = devm_mutex_init(&pdev->dev, &st->lock);
if (ret)
return ret;
ad3552r_hs_debugfs_init(indio_dev);
return ret;
}
static const struct of_device_id ad3552r_hs_of_id[] = {