0

I have a ST7580 Power line communication modem connected to a BeagleBone Black device running Debian Linux, kernel v4.19. I am trying to communicate with the modem using a custom serial driver (using the SERDEV model) which is based on some samples. I have compiled it as a kernel module named st7580km.ko and used modprobe to insert it into the kernel. Since I want to use a DeviceTree overlay to load the driver for this peripheral device, I have copied and modified the BONE-UART1.dts and named it as BONE-ST7580.dts with the following content:

/dts-v1/;
/plugin/;
#include <dt-bindings/pinctrl/am33xx.h>

&{/chosen} {
    overlays {
        BONE-ST7580 = __TIMESTAMP__;
    };
};

&ocp {
    P9_24_pinmux { pinctrl-0 = <&P9_24_uart_pin>; };    /* UART TX*/
    P9_26_pinmux { pinctrl-0 = <&P9_26_uart_pin>; };    /* UART RX*/
};

&bone_uart1 {
    //compatible = "st7580, st7580km, uart, omap3-uart";
    compatible = "st7580, st7580km";
    status = "okay";
};

I have compiled the dts file to dtbo and placed the dtbo in /lib/firmware and also in /boot/dtbs/4.19.94-ti-r73/

The kernel module source:

#include <asm/unaligned.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/serdev.h>

#define ST7580_DRIVER_NAME "st7580"
#define ST7580_DRIVER_VERSION  "0.1.0"
#define ST7580_DEFAULT_BAUD_RATE 57600
#define ST7580_CHECKSUM_LENGTH 2
#define ST7580_MAX_DATA_LENGTH (3 + 255 + ST7580_CHECKSUM_LENGTH )
#define ST7580_TX_ACK_TIMEOUT msecs_to_jiffies(40)

static void st7580_write_wakeup(struct serdev_device *serdev)
{
    dev_info(&serdev->dev, "\nst7580_write_wakeup: pull down RTS\n");
    /* Pull down RTS */
    serdev_device_set_tiocm(serdev, TIOCMBIS, TIOCM_RTS);
}

static int st7580_receive_buf(struct serdev_device *serdev, 
       const unsigned char *buf, size_t size)
{
    dev_info(&serdev->dev, "\nst7580_receive_buf: Received %u bytes\n", size);
    return serdev_controller_receive_buf(serdev, buf, size);
}

static const struct serdev_device_ops st7580_serdev_ops = {
    .receive_buf = st7580_receive_buf, /* default */
    .write_wakeup = st7580_write_wakeup,
};

static int st7580_probe(struct serdev_device *serdev)
{
    int uart_flags;
    int ret;

    dev_info(&serdev->dev, "\nst7580_probe started...");
    serdev_device_set_client_ops(serdev, &st7580_serdev_ops);
    ret = devm_serdev_device_open(&serdev->dev, serdev);
    if (ret) {
        _dev_err(&serdev->dev, "unable to open the device\n");
        return ret;
    }
    serdev_device_set_baudrate(serdev, ST7580_DEFAULT_BAUD_RATE);
    serdev_device_set_flow_control(serdev, false);
    ret = serdev_device_set_parity(serdev, SERDEV_PARITY_NONE);
    uart_flags = 0;
    uart_flags &= ~PARENB;
    uart_flags &= ~CSTOPB;
    uart_flags &= ~CSIZE;
    uart_flags |=  CS8;
    uart_flags &= ~CRTSCTS;
    uart_flags |= CREAD | CLOCAL;
    //uart_settings.c_iflag &= ~(IXON | IXOFF | IXANY);
    //uart_settings.c_iflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    //uart_settings.c_iflag &= ~IGNBRK;
    serdev_device_set_tiocm(serdev, TIOCMSET, uart_flags);
    serdev_device_set_rts(serdev, 0);
    serdev_device_set_tiocm(serdev, TIOCMSET, TIOCM_RTS);
    dev_info(&serdev->dev, "\nDriver name is %s, loaded successsfully\n", ST7580_DRIVER_NAME);
    return ret;
}

static const struct of_device_id st7580_of_match[] = {
    { .compatible = "st7580, st7580km" },
    { .compatible = "st, st7580" },
    { .compatible = "st, st7580km" },
    { }
};
MODULE_DEVICE_TABLE(of, st7580_of_match);

static struct serdev_device_driver st7580_driver = {
    .driver = {
        .name = ST7580_DRIVER_NAME,
        .of_match_table = st7580_of_match,
    },
    .probe = st7580_probe,
};
module_serdev_device_driver(st7580_driver);

I have also modified the /boot/uEnv.txt and added this line to load the DeviceTree overlay.

optargs=quiet drm.debug=7 capemgr.enable_partno=BB-ST7580

When I reboot I expect that my driver will be loaded using which I can communicate to the modem from a userspace app. I have placed some debug messages in the code which I expect to see in the dmesg output like below:

dev_info(&serdev->dev, "\nDriver name is %s, loaded successsfully\n", ST7580_DRIVER_NAME);

So far I do dont see any of the messages and am not sure if the kernel is using my driver for this peripheral. Can any one tell me what I have missed or any errors?

I have SD card enabled and the device boots from that not the eMMC. In the boot logs I dont see the kernel even trying to load the BONE-ST7580.dtbo that is specified in uEnv.txt. I also have CONFIG_SERIAL_DEV_BUS=y CONFIG_SERIAL_DEV_CTRL_TTYPORT=y enabled in the /usr/src/linux-headers-4.19.94-ti-r73/.config file that I used to build the driver as suggested in another post.

Raghu
  • 1
  • 1
  • 1
    Does this answer your question? [Driver code in kernel module doesn't execute?](https://stackoverflow.com/questions/26840267/driver-code-in-kernel-module-doesnt-execute) The compatible string in your DT does not match anything in the driver. – sawdust Jan 23 '23 at 23:31
  • 1
    You really need to learn to put `\n` only **after** the messages. – 0andriy Jan 25 '23 at 09:33
  • 1
    You have a stray space character in the `compatible` property string in the device tree overlay. Also, you should probably use `st` for the vendor name in those strings, for example something like `"st,st7580"`, `"st,st7580km"` and `"st,st7580-fsk-psk"`. (I'm not sure why you need three different compatible strings unless you intend to handle them differently at some time.) – Ian Abbott Jan 25 '23 at 16:24
  • Also, do you know if the device tree overlay was actually loaded? Can beaglebone load device tree overlays for things that are not capes? – Ian Abbott Jan 25 '23 at 16:39
  • Thanks to all who amswered. As regards to the compatible string, I need only st7580, st7580km. I am not intending the handle them differently. >Can beaglebone load device tree overlays for things that are not capes? I am not sure, and checking the boot log, I dont see any output from the boot process that indicates that it is using my BONE-ST7580.dtbo at all. In the /boot/uEnv.txt I have this line: optargs=drm.debug=7 capemgr.enable_partno=BONE-ST7580 As per my understanding this should cause the kernel to load this overlay. – Raghu Jan 30 '23 at 08:35

1 Answers1

0

Step one is to hook up to the debug UART on the Beaglebone. It gives you the necessary low level information to figure out what is happening during the U-Boot phase and early Kernel boot.

For embedded (Linux) work there is no excuse from hooking up to a UART. It's an essential tool.

Things to check for in this case is if you have more than one U-Boot in play (eMMC vs SD) and if you're working with the right one. Also if there are any error messages from U-Boot, etc. It should be quite easy to tell from the UART output.

TBR
  • 2,790
  • 1
  • 12
  • 22
  • 1
    It's not an answer. – 0andriy Jan 25 '23 at 09:34
  • This *is* an answer. It's not a *direct* answer to why the module is not loaded. It does however point out what to look for in terms of U-Boot output and how to ensure that you have the foundation (debug-UART) in place. The OP asked for what they missed, this is addressed by the answer. – TBR Jan 25 '23 at 13:33
  • I have SD card enabled and the device boots from that not the eMMC. I have attached the boot log below: – Raghu Jan 30 '23 at 08:51