mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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:
parent
ca74d0eb06
commit
b1c5d68ea6
|
|
@ -7,6 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/bitfield.h>
|
#include <linux/bitfield.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
#include <linux/iio/backend.h>
|
#include <linux/iio/backend.h>
|
||||||
|
|
@ -54,6 +55,18 @@ struct ad3552r_hs_state {
|
||||||
struct ad3552r_hs_platform_data *data;
|
struct ad3552r_hs_platform_data *data;
|
||||||
/* INTERFACE_CONFIG_D register cache, in DDR we cannot read values. */
|
/* INTERFACE_CONFIG_D register cache, in DDR we cannot read values. */
|
||||||
u32 config_d;
|
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,
|
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);
|
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,
|
static int ad3552r_hs_update_reg_bits(struct ad3552r_hs_state *st, u32 reg,
|
||||||
u32 mask, u32 val, size_t xfer_size)
|
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);
|
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)
|
static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
|
||||||
{
|
{
|
||||||
u16 id;
|
u16 id;
|
||||||
|
|
@ -550,11 +674,7 @@ static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
|
ret = ad3552r_hs_set_data_source(st, IIO_BACKEND_EXTERNAL);
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -661,6 +781,26 @@ static const struct iio_info ad3552r_hs_info = {
|
||||||
.debugfs_reg_access = &ad3552r_hs_reg_access,
|
.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)
|
static int ad3552r_hs_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct ad3552r_hs_state *st;
|
struct ad3552r_hs_state *st;
|
||||||
|
|
@ -705,7 +845,17 @@ static int ad3552r_hs_probe(struct platform_device *pdev)
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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[] = {
|
static const struct of_device_id ad3552r_hs_of_id[] = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user