我的自定义linux gpio模块代码有什么问题?

时间:2019-05-22 13:56:50

标签: linux-kernel kernel-module gpio device-tree

我正在尝试为odroid-c2写一个基于自定义描述符的gpio内核模块。 但是,一旦插入模块,我就会收到错误消息:

OF: /soc/periphs@c8834000/pinctrl@4b0/bank@4b0: could not get #gpio-cells for /soc/periphs@c8834000/pinctrl@4b0

这是我到目前为止编写的代码:

static int __init gpio_test_driver_init(void) {

    int err = 0;
    int gpios;
    struct device_node *np;
    struct pinctrl_dev *pctldev;
    enum of_gpio_flags flags;

    printk(KERN_DEBUG "Init Called\n");

    chip = gpiochip_find("periphs-banks", chip_match_name);

    if (!chip) {
        printk(KERN_ERR "Cannot Find A GPIO Chip");
        return -ENODEV;
    }
    printk(KERN_DEBUG "Got valid GPIO Chip Total num gpios %d\n", chip->ngpio);

    np = chip->of_node;

    if (np == NULL) {
        printk(KERN_ERR "device node is null\n");
        return -ENOMEM;
    }

    gpios = of_get_named_gpio_flags(np, "gpio-ranges", 0, &flags);
    if (gpio_is_valid(gpios)) {
        printk(KERN_ERR "Valid GPIO==> %d\n", gpios);
    }
    else {
        printk(KERN_ERR "Invalid GPIO==> %d\n", gpios);
    }
    return err;
}

dtsi文件如下:meson-gxbb.dtsi

&periphs {
    pinctrl_periphs: pinctrl@4b0 {
        compatible = "amlogic,meson-gxbb-periphs-pinctrl";
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        gpio: bank@4b0 {
            reg = <0x0 0x004b0 0x0 0x28>,
                  <0x0 0x004e8 0x0 0x14>,
                  <0x0 0x00520 0x0 0x14>,
                  <0x0 0x00430 0x0 0x40>;
            reg-names = "mux", "pull", "pull-enable", "gpio";
            gpio-controller;
            #gpio-cells = <2>;
            gpio-ranges = <&pinctrl_periphs 0 0 119>;
        };

        emmc_pins: emmc {
            mux {
                groups = "emmc_nand_d07",
                       "emmc_cmd",
                       "emmc_clk";
                function = "emmc";
                bias-disable;
            };
        };

        emmc_ds_pins: emmc-ds {
            mux {
                groups = "emmc_ds";
                function = "emmc";
                bias-disable;
            };
        };

        emmc_clk_gate_pins: emmc_clk_gate {
            mux {
                groups = "BOOT_8";
                function = "gpio_periphs";
                bias-pull-down;
            };
        };

        nor_pins: nor {
            mux {
                groups = "nor_d",
                       "nor_q",
                       "nor_c",
                       "nor_cs";
                function = "nor";
                bias-disable;
            };
        };

        spi_pins: spi-pins {
            mux {
                groups = "spi_miso",
                    "spi_mosi",
                    "spi_sclk";
                function = "spi";
                bias-disable;
            };
        };

        spi_ss0_pins: spi-ss0 {
            mux {
                groups = "spi_ss0";
                function = "spi";
                bias-disable;
            };
        };

        sdcard_pins: sdcard {
            mux {
                groups = "sdcard_d0",
                       "sdcard_d1",
                       "sdcard_d2",
                       "sdcard_d3",
                       "sdcard_cmd",
                       "sdcard_clk";
                function = "sdcard";
                bias-disable;
            };
        };

        sdcard_clk_gate_pins: sdcard_clk_gate {
            mux {
                groups = "CARD_2";
                function = "gpio_periphs";
                bias-pull-down;
            };
        };

        sdio_pins: sdio {
            mux {
                groups = "sdio_d0",
                       "sdio_d1",
                       "sdio_d2",
                       "sdio_d3",
                       "sdio_cmd",
                       "sdio_clk";
                function = "sdio";
                bias-disable;
            };
        };

        sdio_clk_gate_pins: sdio_clk_gate {
            mux {
                groups = "GPIOX_4";
                function = "gpio_periphs";
                bias-pull-down;
            };
        };

        sdio_irq_pins: sdio_irq {
            mux {
                groups = "sdio_irq";
                function = "sdio";
                bias-disable;
            };
        };

        uart_a_pins: uart_a {
            mux {
                groups = "uart_tx_a",
                       "uart_rx_a";
                function = "uart_a";
                bias-disable;
            };
        };

        uart_a_cts_rts_pins: uart_a_cts_rts {
            mux {
                groups = "uart_cts_a",
                       "uart_rts_a";
                function = "uart_a";
                bias-disable;
            };
        };

        uart_b_pins: uart_b {
            mux {
                groups = "uart_tx_b",
                       "uart_rx_b";
                function = "uart_b";
                bias-disable;
            };
        };

        uart_b_cts_rts_pins: uart_b_cts_rts {
            mux {
                groups = "uart_cts_b",
                       "uart_rts_b";
                function = "uart_b";
                bias-disable;
            };
        };

        uart_c_pins: uart_c {
            mux {
                groups = "uart_tx_c",
                       "uart_rx_c";
                function = "uart_c";
                bias-disable;
            };
        };

        uart_c_cts_rts_pins: uart_c_cts_rts {
            mux {
                groups = "uart_cts_c",
                       "uart_rts_c";
                function = "uart_c";
                bias-disable;
            };
        };

        i2c_a_pins: i2c_a {
            mux {
                groups = "i2c_sck_a",
                       "i2c_sda_a";
                function = "i2c_a";
                bias-disable;
            };
        };

        i2c_b_pins: i2c_b {
            mux {
                groups = "i2c_sck_b",
                       "i2c_sda_b";
                function = "i2c_b";
                bias-disable;
            };
        };

        i2c_c_pins: i2c_c {
            mux {
                groups = "i2c_sck_c",
                       "i2c_sda_c";
                function = "i2c_c";
                bias-disable;
            };
        };

        eth_rgmii_pins: eth-rgmii {
            mux {
                groups = "eth_mdio",
                       "eth_mdc",
                       "eth_clk_rx_clk",
                       "eth_rx_dv",
                       "eth_rxd0",
                       "eth_rxd1",
                       "eth_rxd2",
                       "eth_rxd3",
                       "eth_rgmii_tx_clk",
                       "eth_tx_en",
                       "eth_txd0",
                       "eth_txd1",
                       "eth_txd2",
                       "eth_txd3";
                function = "eth";
                bias-disable;
            };
        };

        eth_rmii_pins: eth-rmii {
            mux {
                groups = "eth_mdio",
                       "eth_mdc",
                       "eth_clk_rx_clk",
                       "eth_rx_dv",
                       "eth_rxd0",
                       "eth_rxd1",
                       "eth_tx_en",
                       "eth_txd0",
                       "eth_txd1";
                function = "eth";
                bias-disable;
            };
        };

        pwm_a_x_pins: pwm_a_x {
            mux {
                groups = "pwm_a_x";
                function = "pwm_a_x";
                bias-disable;
            };
        };

        pwm_a_y_pins: pwm_a_y {
            mux {
                groups = "pwm_a_y";
                function = "pwm_a_y";
                bias-disable;
            };
        };

        pwm_b_pins: pwm_b {
            mux {
                groups = "pwm_b";
                function = "pwm_b";
                bias-disable;
            };
        };

        pwm_d_pins: pwm_d {
            mux {
                groups = "pwm_d";
                function = "pwm_d";
                bias-disable;
            };
        };

        pwm_e_pins: pwm_e {
            mux {
                groups = "pwm_e";
                function = "pwm_e";
                bias-disable;
            };
        };

        pwm_f_x_pins: pwm_f_x {
            mux {
                groups = "pwm_f_x";
                function = "pwm_f_x";
                bias-disable;
            };
        };

        pwm_f_y_pins: pwm_f_y {
            mux {
                groups = "pwm_f_y";
                function = "pwm_f_y";
                bias-disable;
            };
        };

        hdmi_hpd_pins: hdmi_hpd {
            mux {
                groups = "hdmi_hpd";
                function = "hdmi_hpd";
                bias-disable;
            };
        };

        hdmi_i2c_pins: hdmi_i2c {
            mux {
                groups = "hdmi_sda", "hdmi_scl";
                function = "hdmi_i2c";
                bias-disable;
            };
        };

        i2sout_ch23_y_pins: i2sout_ch23_y {
            mux {
                groups = "i2sout_ch23_y";
                function = "i2s_out";
                bias-disable;
            };
        };

        i2sout_ch45_y_pins: i2sout_ch45_y {
            mux {
                groups = "i2sout_ch45_y";
                function = "i2s_out";
                bias-disable;
            };
        };

        i2sout_ch67_y_pins: i2sout_ch67_y {
            mux {
                groups = "i2sout_ch67_y";
                function = "i2s_out";
                bias-disable;
            };
        };

        spdif_out_y_pins: spdif_out_y {
            mux {
                groups = "spdif_out_y";
                function = "spdif_out";
                bias-disable;
            };
        };
    };
};

我想在linux模块中访问gpio,但是我无法获得它。在特定节点“ gpio:bank @ 4b0”的dtsi文件中,单元数被称为“#gpio-cells = <2>;”。但即使我遇到错误。


更新:

我修改了要使用的代码,并修改了现有的在内核空间中运行的引脚控制驱动程序,并且依赖于此。
我已经使用了该驱动程序的API,并且按预期方式工作,我正在尝试和学习,因此下面的代码仅供参考:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/printk.h>
#include <linux/init.h>
#include <linux/delay.h>

#include <linux/gpio/driver.h>
#include <dt-bindings/gpio/meson-gxbb-gpio.h>

struct gpio_chip *chip;

static int chip_match_name(struct gpio_chip *chip, void *data)
{
    printk(KERN_INFO "Label: %s", chip->label);
    printk(KERN_INFO "Name: %s", chip->parent->init_name);
    printk(KERN_INFO "OF Node Full Name: %s", chip->of_node->full_name);

    return !strcmp(chip->label, data);
}

int gpio_test_init(void)
{
    int err = 0;

    printk(KERN_DEBUG "Init Called\n");

    chip = gpiochip_find("periphs-banks", chip_match_name);

    if (!chip) {
        printk(KERN_ERR "Cannot Find A GPIO Chip");
        return -ENODEV;
    }
    printk(KERN_DEBUG "Got valid GPIO Chip Total num gpios %d\n",
            chip->ngpio);

    err = chip->get(chip, GPIOX_11);
    printk(KERN_INFO "Before Setting Value %d\n", err);

    err = chip->direction_output(chip, GPIOX_11, 1);
    if (err < 0) {
        printk(KERN_DEBUG "Error Setting GPIO Direction %d", err);
    }
    chip->set(chip, GPIOX_11, 1);

    err = chip->get(chip, GPIOX_11);
    printk(KERN_INFO "After Setting Value %d\n", err);

    mdelay(2000);

    chip->set(chip, GPIOX_11, 0);

    err = chip->get(chip, GPIOX_11);
    printk(KERN_INFO "After Clearing Value %d\n", err);

    return 0;
}

void gpio_test_exit(void)
{
    printk(KERN_DEBUG "Exiting....\n");
}

module_init( gpio_test_init);
module_exit( gpio_test_exit);

MODULE_LICENSE("GPL");  

我不确定这是否是访问GPIO的正确方法。
如果我做错了,请纠正我。

0 个答案:

没有答案