ADC reading from kernel module

56 views
Skip to first unread message

droland

unread,
Feb 25, 2021, 7:17:22 AM2/25/21
to BeagleBoard

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


droland

unread,
Mar 8, 2021, 10:21:03 AM3/8/21
to BeagleBoard
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




pierric...@gadz.org

unread,
Mar 8, 2021, 4:08:38 PM3/8/21
to BeagleBoard

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
Reply all
Reply to author
Forward
0 new messages