A10: Slow toggling of GPIO by writing directly to registers from kernel-module

Started by Felipito, July 27, 2015, 03:43:17 PM

Previous topic - Next topic

Felipito

Hi all,

I am trying to toggle an output-GPIO (PI0) as fast as possible by using a kernel-module (see below code) that directly writes to the corresponding GPIO-register (physical address: 0x01c20800 + 0x130). But due some unknown reason, the toggle only works reliable if I use a delay greater 20 microseconds between setting and resetting the line. I expected to achieve some nano-seconds as minimal delay. For this reason, I think there is something wrong with my GPIO-configuration.

Now, have somebody tried to speed up the GPIO-toggling on that way? or give me a hint for solving this issue? Thanks in advance.

BR,

Luis


#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/platform_device.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Luis");

#define MY_GPIO_CLK           (49)
#define SW_PA_PORTC_IO_BASE      0x01c20800
#define CSP_PIN_PHY_ADDR_SIZE    0x1000

static int write_delay = 0;
static void __iomem *my_io = NULL;

static struct gpio my_gpios[] = {
    { MY_GPIO_CLK, GPIOF_OUT_INIT_LOW, "clock" },
};

static void sunxi_gpio_write_raw(u32 value)
{
        u32 val;

        if (write_delay) {
            ndelay(write_delay);
        }

        iowrite32(value, my_io + 0x130);

        val = ioread32(my_io + 0x130);
        if (value != val) {
            printk(KERN_ERR "Failed iowrite32() | %i %i\n", value, val);
        }
}

static int wago_write_byte(u8 data)
{
    uint pos;

    write_delay = 200;

    for (pos = 0; pos < 2; pos++) {
        //gpio_set_value(MY_GPIO_CLK, 1);
        sunxi_gpio_write_raw(1);

        //gpio_set_value(MY_GPIO_CLK, 0);
        sunxi_gpio_write_raw(0);
    }

    return 0;
}

static __init int wago_init(void)
{
    int err;

    my_io = ioremap_nocache(SW_PA_PORTC_IO_BASE, CSP_PIN_PHY_ADDR_SIZE);
    if (NULL == my_io) {
        printk(KERN_ERR "Failed to ioremap()\n");
        return -EIO;
    }

    err = gpio_request_array(my_gpios, ARRAY_SIZE(my_gpios));
    if (err) {
        iounmap(my_io);
        printk(KERN_ERR "Couldn't request GPIOs, %i\n", err);
        return err;
    }

    wago_write_byte(0xaa);
    printk(KERN_INFO "WAGO module loaded " __TIME__ "\n");
    return 0;
}

static __exit void wago_exit(void)
{
    gpio_free_array(my_gpios, ARRAY_SIZE(my_gpios));
    iounmap(my_io);
}

module_init(wago_init);
module_exit(wago_exit);


JohnS

Don't expect more than about 4MHz as there appear to be weird internal interlocks in the chip itself.

John

Felipito

Quote from: JohnS on July 27, 2015, 05:58:41 PM
Don't expect more than about 4MHz as there appear to be weird internal interlocks in the chip itself.

Thanks for the info, but at this moment I have about 50kHz. I would be happy to see 2MHz as I need it for generating a bus clock.

I haven't tested with another GPIO than PI0. Could be a problem of this specific line? I will test it at this evening.

Luis

JohnS

It seems to me it will never be a sensible way to create a clock, let alone quite a fast one.  I'd use an existing peripheral type.

John