ADC reading from kernel module

Hello,

I can read/write gpio pins from the kernel module, but now I should read/access ADC channels from the kernel modules.
I found some examples, but each uses file access with the open / read / close commands. they work well in user space but not in kernel space.

Some sample code uses sysfs_open with changing code segment (KERNEL_DS) (Unfortunately) I could not compile my module because the sysfs commands were not exported in Linux source and I think the file operations is not a good idea in kernel space.

I’m working on a custom build Linux with 5.4 kernel on Beaglebone Black. Thanks to some articles by Derek Molloy, I can access to gpio, but I got stuck at the ADC (iio).
(I see and I can read the /sys/bus/iio/devices/iio:device0/in_voltageX_raw and in user space works fine.)

What is the correct mode or how can I read ADC channels from the kernel space/module (without segment manipulation)?
(I’m also interested in using the UART in kernel module…)

Please, anyone help me with any useful information.

Thank you in advance.

Roland Dobak

Hello,

I find an “adc” device by the following code:

struct device dev;

static int custom_match_dev(struct device *dev, const void *data)
{
// this function implements the comaparison logic. Return not zero if found.
const char *name = data;
int result = 0;

if (dev == NULL)
return result;

if (dev->of_node == NULL)
return result;

if (dev->of_node->name == NULL)
return result;

result = sysfs_streq(name, dev->of_node->name);
return result;
}

static struct device *find_dev(const char *name)
{
struct device *dev = NULL;
dev = bus_find_device(&platform_bus_type, NULL, name, custom_match_dev);
return dev;

}

and there is an “adc” here:
~# cat /sys/bus/platform/devices/TI-am335x-adc.2.auto/of_node/name
adc

~# ls /sys/bus/platform/devices/TI-am335x-adc.2.auto/of_node/
#io-channel-cells compatible name ti,adc-channels

~# ls /sys/bus/platform/devices/TI-am335x-adc.2.auto
driver iio:device0 of_node subsystem
driver_override modalias power uevent

~# ls /sys/bus/iio/devices/iio:device0/
buffer/ in_voltage2_raw in_voltage6_raw power/
dev in_voltage3_raw in_voltage7_raw scan_elements/
in_voltage0_raw in_voltage4_raw name subsystem/
in_voltage1_raw in_voltage5_raw of_node/ uevent

When I try to get the iio channels with devm_IIo_channel_get or devm_IIo_channel_get_all. I always get -19 answer (no such device). I also tried the iio_channel_get and iio_channel_get_all and the result is same.

struct iio_channel *channels;
channels = iio_channel_get(dev, “iio:device0”);
if (IS_ERR(channels))
{
printk(KERN_ERR “channels: %d\n”, (int)channels);
//return 0;
return PTR_ERR(channels);
}

At the iio_channel_get second parameter I tried various stings like channel number and other strings I found under /sys/bus/iio… and path above.

What is wrong with this code?

Please give me any advice how I read adc channels in kernel space.

Thank you in advance.
Roland Dobak

droland a következőt írta (2021. február 25., csütörtök, 13:17:22 UTC+1):

Hi Roland,

I am not sure that I completely understand your question but have you looked at the iio_generic_buffer (https://github.com/torvalds/linux/blob/master/tools/iio/iio_generic_buffer.c)? I did something similar 3 years ago and used this example to sample the BBB ADC using the iio driver and read the results in userspace after.
Sorry if I am way off the mark here.

Best
Pierrick