0

For one of my projects I'm slightly modifying the Linux serial driver, so I can drive a GPIO pin to 1 right before a Tx session starts and to 0 again after the session ends. I'm doing this by including the gpio header in the driver and calling the appropriate functions:

EDIT: After the suggestions of @sawdust in the comments the new code looks like this

In Tx start:

static void imx_start_tx(struct uart_port *port)
{
    struct imx_port *sport = (struct imx_port *)port;
    unsigned long temp;

    gpio_set_value(140, 1);

In Tx stop:

static void imx_stop_tx(struct uart_port *port)
{
    struct imx_port *sport = (struct imx_port *)port;
    unsigned long temp;

    gpio_set_value(140, 0);

While the GPIO request is being done in the imx_startup:

static int imx_startup(struct uart_port *port)
{
    struct imx_port *sport = (struct imx_port *)port;
    int retval, i;
    unsigned long flags, temp;

    /* Request GPIO #140, used for control flow */
    int gpio_num = 140;
    const char* label = "f";

    if (!gpio_is_valid(gpio_num)){
        printk(KERN_INFO "GPIO_RS485: invalid GPIO pin\n");
        return -ENODEV;
    }

    int gpio_req = gpio_request(gpio_num, label);

    if(gpio_req != 0){
        printk(KERN_INFO "GPIO_RS485: GPIO access request failed with %d\n", gpio_req); 
    } else {
        printk(KERN_INFO "GPIO_RS485: GPIO access request succeeded!\n");
    }

And the gpio_free(); is being called in imx_shutdown

static void imx_shutdown(struct uart_port *port)
{
    struct imx_port *sport = (struct imx_port *)port;
    unsigned long temp;
    unsigned long flags;
    gpio_free(140);

However the issue persists. Another thing is that now I'm getting the following messages in dmesg, which means that the driver is being initialized several times?

dmesg output

EDIT ENDS HERE

The problem with this code is that I can confirm that the pin is correctly being driven to 1, but then it never gets back to 0. Why is this happening and how can I fix this?

Arkoudinos
  • 1,099
  • 12
  • 20
  • 1
    You fail to check the return values for error conditions. You're also misusing **gpio_request()** and **gpio_free()**. The former should be called when the driver does init/probe, and the latter when the driver cleans up on exit. – sawdust Oct 05 '18 at 20:56
  • So if I understand you correctly, I should take control of the pin during the init of the driver, keep it for as long as the driver runs, and then return it to the system. In the meantime, I need to check the return values of the functions, to check if specific error conditions apply. Right? – Arkoudinos Oct 08 '18 at 00:11
  • Yes. It may not directly solve the problem, but your driver will be more efficient and robust (i.e. not ignore error conditions). – sawdust Oct 08 '18 at 08:39
  • Many thanks for the suggestion. Unfortunately it didn't solve it. The only useful output was during the boot, where kernel complained for not being able to access the pin due to error -16 (I think it means busy). On the other hand, still, when I run my app and start transmitting it goes to 1, but never to 0 :/ – Arkoudinos Oct 08 '18 at 09:50
  • *" the driver is being initialized several times?"* -- No, you're confusing driver initialization with port initialization. **imx_startup()** is called for every UART in your system. How many ports does your system have? Your code (with a hardcoded GPIO number) could only work for a single UART. What Linux kernel version is this? Since 4.1 the [*drivers/tty/serial/imx.c*](https://elixir.bootlin.com/linux/v4.1/source/drivers/tty/serial/imx.c#L1549) has support for RS-485. – sawdust Oct 09 '18 at 06:35
  • The system has two ports, both of them are RS-232. The kernel version is indeed 4.1 (4.1.15). Also, I'm using on purpose the hardcoded number, since this is the only GPIO pin I want to use, and also with only one of the serial ports (the second one is being used for debugging purposes). The reason why am I using this GPIO pin, is to control the direction of an RS485 - to - RS232 converter, since my system lacks the RTS/CTS signals. – Arkoudinos Oct 09 '18 at 09:26

0 Answers0