本帖最后由 星空 于 2021-9-26 21:06 编辑
1 gpio的状态调试
1.1 gpio状态查看- adb 操作mt8788的gpio地址,每个平台不一样.
- cat sys/devices/platform/1000b000.pinctrl/mt_gpio
复制代码
1.2 gpio状态设置
- 设置模式:echo mode 14 0 > mt_gpio
- 设置输入/输出:echo dir 14 1 > mt_gpio
- 输出高/低:echo out 14 1 > mt_gpio
- 设置pullen: echo pullen 14 1 > mt_gpio
- gpio 状态用adb 查看,可以定位gpio的复用等导致的一些问题.
复制代码
2 gpio的控制
2.1 pinctrl系统的方式LInux针对PIN的配置推出了pinctrl子系统,针对GPIO的配置推出了gpio子系统。如果 pinctrl 子系统将一个 PIN 复用为 GPIO ,那么接下来就要用到 gpio 子系
统了。2.1.1 简介
在许多soc内部都包含有pin控制器,通过pin控制器的寄存器,我们可以配置一个或者一组引脚的功能和特性。在软件方面,Linux内核提供了pinctrl子系统,目的是为了统一各soc厂商的pin脚管理。
比如有些I/O口具有不同的状态(state),在正常工作的时候这一组I/O口被配置成uart接口,休眠时配置成GPIO接口且输出为高电平
使用pinctrl的主要目标有两个: (1)设定该设备的功能复用。 (2)设定该device对应的pin的电气特性。
pinctrl子系统的优点:有了pinctrl子系统以后,驱动就可以操作pinctrl子系统的接口函数完成I/O操作了,而不需要自己去配置了。 使用场景: 建议所有pin脚定义都使用pinctrl(除输入和对输出的速度有要求的gpio脚除外) 2.1.2 使用
2.1.3 实例- &pio{
- gpio_pins_default:
- gpiodefault {
- };
- gpio_pins_eint6_as_int:
- eint@00 {
- pins_cmd_dat {
- pinmux = <PINMUX_GPIO6__FUNC_GPIO6>;
- slew-rate = <0>;
- bias-disable;
- };
- };
- gpio_pins_eint17_as_int:
- eint@1 {
- pins_cmd_dat {
- pinmux = <PINMUX_GPIO17__FUNC_GPIO17>;
- slew-rate = <0>;
- bias-disable;
- };
- };
- gpio_pins_eint18_as_int:
- eint@2 {
- pins_cmd_dat {
- pinmux = <PINMUX_GPIO18__FUNC_GPIO18>;
- slew-rate = <0>;
- bias-disable;
- };
- };
- };
-
- &gpio_input
- {
- compatible = "mediatek,gpio_input";
- pinctrl-names = "pin_default","state_eint6_as_int","state_eint17_as_int","state_eint18_as_int";
- pinctrl-0 = <&gpio_pins_default>;
- pinctrl-1 = <&gpio_pins_eint6_as_int>;
- pinctrl-2 = <&gpio_pins_eint17_as_int>;
- pinctrl-3 = <&gpio_pins_eint18_as_int>;
- interrupt-parent = <&pio>;
- interrupts = <6 IRQ_TYPE_LEVEL_LOW 6 0>,<17 IRQ_TYPE_LEVEL_LOW 17 0>,<18 IRQ_TYPE_LEVEL_LOW 18 0>;
- deb-gpios0 = <&pio 6 0>;
- deb-gpios1 = <&pio 17 0>;
- deb-gpios2 = <&pio 18 0>;
- debounce = <1000>;
- status = "okay";
- };
-
- static int gpio_input_dev_init(struct platform_device *pdev)
- {
- int err = -1;
- GPIO_LOG("%s \n",__func__);
-
- gpioInputDevice->pinctrl = devm_pinctrl_get(&pdev->dev);
- if (IS_ERR(gpioInputDevice->pinctrl))
- {
- err = PTR_ERR(gpioInputDevice->pinctrl);
- GPIO_LOG(" %s fwq Cannot find pinctrl! err=%d \n",__func__,err);
- return err;
- }
-
- gpioInputDevice->eint6_as_int = pinctrl_lookup_state(gpioInputDevice->pinctrl, "state_eint6_as_int");
- if (IS_ERR(gpioInputDevice->eint6_as_int))
- {
- err = PTR_ERR(gpioInputDevice->eint6_as_int);
- GPIO_LOG(" %s Cannot find pinctrl eint6_as_int! err=%d \n",__func__,err);
- return err;
- }
-
- gpioInputDevice->eint17_as_int = pinctrl_lookup_state(gpioInputDevice->pinctrl, "state_eint17_as_int");
- if (IS_ERR(gpioInputDevice->eint17_as_int))
- {
- err = PTR_ERR(gpioInputDevice->eint17_as_int);
- GPIO_LOG(" %s Cannot find pinctrl eint17_as_int! err=%d \n",__func__,err);
- return err;
- }
- gpioInputDevice->eint18_as_int = pinctrl_lookup_state(gpioInputDevice->pinctrl, "state_eint18_as_int");
- if (IS_ERR(gpioInputDevice->eint18_as_int))
- {
- err = PTR_ERR(gpioInputDevice->eint18_as_int);
- GPIO_LOG(" %s Cannot find pinctrl eint18_as_int!err=%d \n",__func__,err);
- return err;
- }
-
- pinctrl_select_state(gpioInputDevice->pinctrl, gpioInputDevice->eint6_as_int);
- pinctrl_select_state(gpioInputDevice->pinctrl, gpioInputDevice->eint17_as_int);
- pinctrl_select_state(gpioInputDevice->pinctrl, gpioInputDevice->eint18_as_int);
-
-
- gpioInputDevice->node = of_find_compatible_node(NULL, NULL, "mediatek,gpio_input");
-
- if (!gpioInputDevice->node)
- {
- GPIO_LOG(" %s can't find compatible gpioInputDevice->node\n", __func__);
- return -1;
- }
- gpioInputDevice->gpiopin0 = of_get_named_gpio(gpioInputDevice->node, "deb-gpios0", 0);
- gpioInputDevice->gpiopin1 = of_get_named_gpio(gpioInputDevice->node, "deb-gpios1", 0);
- gpioInputDevice->gpiopin2 = of_get_named_gpio(gpioInputDevice->node, "deb-gpios2", 0);
-
- err = of_property_read_u32(gpioInputDevice->node, "debounce", &gpioInputDevice->gpio_deb);
- if (err < 0)
- {
- GPIO_LOG(" %s gpiodebounce not found,err:%d\n",
- __func__, err);
- return err;
- }
- else
- {
- GPIO_LOG("[%s] debounce=%d.\n",__func__,gpioInputDevice->gpio_deb);
- }
- gpio_set_debounce(gpioInputDevice->gpiopin0, gpioInputDevice->gpio_deb);
- gpio_set_debounce(gpioInputDevice->gpiopin1, gpioInputDevice->gpio_deb);
- gpio_set_debounce(gpioInputDevice->gpiopin2, gpioInputDevice->gpio_deb);
-
- GPIO_LOG(" %s gpioInputDevice->gpiopin0:%d\n",__func__, gpioInputDevice->gpiopin0);
-
- GPIO_LOG(" %s gpioInputDevice->gpiopin1:%d\n",__func__, gpioInputDevice->gpiopin1);
- if (gpioInputDevice->node)
- {
-
- gpioInputDevice->irq6 = irq_of_parse_and_map(gpioInputDevice->node, 0);
- GPIO_LOG("[%s] request_irq irq6=%d.\n", __func__,gpioInputDevice->irq6);
- err = request_irq(gpioInputDevice->irq6, gpio_input_irq6_thread_fn,
- IRQ_TYPE_LEVEL_LOW, "gpio_input_irq6", NULL);
- if (err != 0)
- printk(" request_irq IRQ6 LINE NOT AVAILABLE!.err=%d \n",err);
-
- gpioInputDevice->irq17 = irq_of_parse_and_map(gpioInputDevice->node, 1);
- GPIO_LOG("[%s] request_irq irq17=%d.\n", __func__,gpioInputDevice->irq17);
- err = request_irq(gpioInputDevice->irq17, gpio_input_irq17_thread_fn,
- IRQ_TYPE_LEVEL_LOW, "gpio_input_irq17", NULL);
- if (err != 0)
- printk(" request_irq IRQ17 LINE NOT AVAILABLE!.err=%d \n",err);
-
- gpioInputDevice->irq18 = irq_of_parse_and_map(gpioInputDevice->node, 2);
- GPIO_LOG("[%s] request_irq irq18=%d.\n", __func__,gpioInputDevice->irq18);
- err = request_irq(gpioInputDevice->irq18, gpio_input_irq18_thread_fn,
- IRQ_TYPE_LEVEL_LOW, "gpio_input_irq18", NULL);
- if (err != 0)
- printk(" request_irq IRQ18 LINE NOT AVAILABLE!.err=%d \n",err);
-
- }
- else
- {
- printk("[%s] request_irq can not find touch eint device node!.", __func__);
- }
-
-
-
- return err;
- }
-
复制代码
2.2 gpio子系统的方式
gpio子系统的优点: 1 比pinctl 子系统要快 2 有api可以得到gpio输入的值
使用场景: gpio是输入引脚,或者输出的速度有要求的
- 1 Z:\H10\kernel-4.9\arch\arm64\boot\dts\mediatek\k65v1_64_bsp.dts
-
- &i2c1 {
- pac7620@73 {
- compatible = "mediatek,pac7620";
- reg = <0x73>;
- interrupt-parent = <&pio>;
- interrupts = <4 IRQ_TYPE_EDGE_FALLING 4 0>;
- gpio_vled_pac7620 = <&pio 2 0x0>;
-
- status = "okay";
- };
- };
-
- 2 Z:\H10\kernel-4.9\arch\arm64\boot\dts\mediatek\mt6765.dts
-
- pac7620: pac7620 {
- compatible = "mediatek,pac7620";
- };
- 3 编写函数
- 头文件 #include <linux/of_gpio.h>
-
- static int pac7620_dev_init(struct platform_device *pdev)
- {
- int ret = -1;
-
- pac7620_log("%s\n",__func__);
-
- pac7620Device->node = of_find_compatible_node(NULL, NULL,
- "mediatek,pac7620");
- if (pac7620Device->node) {
- /*touch_irq = gpio_to_irq(tpd_int_gpio_number);*/
- pac7620Device->irq = irq_of_parse_and_map(
- pac7620Device->node, 0);
- pac7620_log("[%s] request_irq irq=%d.", __func__,
- pac7620Device->irq);
-
- ret = request_irq(pac7620Device->irq,
- pac7620_irq_thread_fn,
- IRQF_TRIGGER_FALLING,
- "pac7620_irq", NULL);
-
- if (ret > 0)
- pac7620_err(" request_irq IRQ LINE NOT
- AVAILABLE!.");
- } else {
- pac7620_log("[%s] request_irq can not find touch
- eint device node!.", __func__);
- }
-
- pac7620_log("%s\n",__func__);
- pac7620Device->gpio_vled = of_get_named_gpio(
- pac7620Device->node, "gpio_vled_pac7620", 0);
-
- ret = gpio_request(pac7620Device->gpio_vled,"vled");
- if (ret) {
- printk("error: pac7620Device gpio_request\n");
- return -1;
- }
- ret = gpio_direction_output(pac7620Device->gpio_vled, 1);
- if (ret) {
- printk("error %s : pac7620Device gpio_vled
- gpio_direction_output failed\n",__FILE__);
- ret = -1;
- }
-
-
- INIT_WORK(&pac7620Device->work, pac7620_work_handler);
-
- return 1;
-
- }
- struct pac7620 {
-
- unsigned int gpio_vled;
-
- struct device_node *node ;
- struct platform_device *pdev;
- struct device *dev;
-
- struct i2c_client *client;
- struct input_dev *keyboard_input_dev;
- int irq;
- bank_e bank;
-
- struct work_struct work;
-
- void (*work_handler)(struct work_struct *work);
- };
-
复制代码
3 gpio 状态不对
驱动初始化的时候把gpio口的状态初始化下
dws里gpio配置是否有配对
设备树里查看是否有复用.
代码里是否有复用,这种是接申请的,搜索gpio_request或者平台自带的操作函数
|