<Linux> pinctrl MTK 举例

本文详细介绍了MT6797平台中pinctrl的使用方法,特别是针对pin复用的情况,通过具体的DTS配置示例及driver代码解析,展示了如何设置不同状态下的pin功能。

android kernel dts中的pinctrl用于pin复用的情况.

Spec

如以下为MT6797 GPIO的应用Spec:
这里写图片描述

对应DTS

&pio {
    ctp_pins_default: eint0default {
    };
    ctp_pins_eint_as_int: eint@0 {
        pins_cmd_dat {
            pins = <PINMUX_GPIO65__FUNC_EINT4>;
            slew-rate = <0>;
            bias-disable;
        };
    };
};
&touch {
    pinctrl-names = "default", "state_eint_as_int"
    pinctrl-0 = <&ctp_pins_default>;
    pinctrl-1 = <&ctp_pins_eint_as_int>;
};

其中PINMUX_GPIO65__FUNC_EINT4 定义在
include/dt-bindings/pinctrl/mt6797-pinfunc.h

#define PINMUX_GPIO65__FUNC_GPIO65 (MTK_PIN_NO(65) | 0)
#define PINMUX_GPIO65__FUNC_EINT4 (MTK_PIN_NO(65) | 1)
#define PINMUX_GPIO65__FUNC_CLKM0 (MTK_PIN_NO(65) | 2)
#define PINMUX_GPIO65__FUNC_SPI5_CLK_B (MTK_PIN_NO(65) | 3)
#define PINMUX_GPIO65__FUNC_I2S1_LRCK (MTK_PIN_NO(65) | 4)
#define PINMUX_GPIO65__FUNC_PWM_A (MTK_PIN_NO(65) | 5)
#define PINMUX_GPIO65__FUNC_C2K_DM_EINT2 (MTK_PIN_NO(65) | 7)

driver代码

获取pinctrl
int parse_dt(struct platform_device *pdev)
{
    // ...
    pinctrl1 = devm_pinctrl_get(&pdev->dev);
    if (IS_ERR(pinctrl1)) {
        ret = PTR_ERR(pinctrl1);
        dev_err(&pdev->dev, "fwq Cannot find touch pinctrl1!\n");
        return ret;
    }
    pins_default = pinctrl_lookup_state(pinctrl1, "default");
    if (IS_ERR(pins_default)) {
        ret = PTR_ERR(pins_default);
        dev_err(&pdev->dev, "fwq Cannot find touch pinctrl default %d!\n", ret);
    }
    eint_as_int = pinctrl_lookup_state(pinctrl1, "state_eint_as_int");
    if (IS_ERR(eint_as_int)) {
        ret = PTR_ERR(eint_as_int);
        dev_err(&pdev->dev, "fwq Cannot find touch pinctrl state_eint_as_int!\n");
        return ret;
    }
}

使能PIN

pinctrl_select_state(pinctrl1, eint_as_int);
行 6173: <6>[ 10.091983][ T11] <<GT1151-INF>>[gt1x_ts_gpio_setup:636] GPIO setup,reset-gpio:-2, irq-gpio:-2 行 12746: <6>[ 24.258413][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 12748: <6>[ 24.262434][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 12753: <6>[ 24.267476][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11 行 12778: <6>[ 24.283528][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 12783: <6>[ 24.288634][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 0 行 12785: <6>[ 24.292998][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 12796: <6>[ 24.293092][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 12797: <6>[ 24.294104][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 12802: <6>[ 24.298291][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11 行 12834: <6>[ 24.314529][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 12839: <6>[ 24.318600][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 0 行 12840: <6>[ 24.319610][ T1383] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 13446: <6>[ 34.997793][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 13448: <6>[ 35.001819][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 13453: <6>[ 35.006852][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11 行 13478: <6>[ 35.023376][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 13483: <6>[ 35.028517][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 0 行 13485: <6>[ 35.032572][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 13496: <6>[ 35.032617][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 13497: <6>[ 35.033620][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 13502: <6>[ 35.037652][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11 行 13534: <6>[ 35.053784][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 13539: <6>[ 35.058392][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 0 行 13540: <6>[ 35.059405][ T2151] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 14210: <6>[ 44.432094][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 14212: <6>[ 44.436137][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 14217: <6>[ 44.441183][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11 行 14242: <6>[ 44.456777][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 14247: <6>[ 44.461820][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 0 行 14249: <6>[ 44.465834][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 14260: <6>[ 44.465876][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 14261: <6>[ 44.466880][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 14266: <6>[ 44.470901][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11 行 14298: <6>[ 44.487088][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 14303: <6>[ 44.491147][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 0 行 14304: <6>[ 44.492152][ T2403] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 16074: <6>[ 50.747718][ T2794] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 0 行 16076: <6>[ 50.752332][ T2794] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 3, Val 9 行 16081: <6>[ 50.757431][ T2794] [imgsensor][gpio_set] gpio_set : pinctrl err, PinIdx 2, Val 11
最新发布
10-19
### 修改后的设备树配置 在 `mtk_flashlights_mumbai` 节点中添加 GPIO 配置,并设置为初始高电平: ```dts &i2c6 { status = "okay"; clock-frequency = <400000>; mediatek,use-push-pull; #address-cells = <1>; #size-cells = <0>; mtk_flashlights_mumbai: flashlights_mumbai@63 { compatible = "mediatek,strobe_main"; reg = <0x63>; status = "okay"; /* 添加使能GPIO配置 */ enable-gpios = <&pio 123 GPIO_ACTIVE_HIGH>; // 假设使用GPIO123 gpio-initial-state = "high"; // 初始高电平 }; }; &flashlights_mumbai { status = "okay"; flash@0 { reg = <0>; type = <0>; ct = <0>; part = <0>; port@0 { fl_core_0: endpoint { remote-endpoint = <&flashlight_0>; }; }; }; }; ``` ### 驱动代码实现 ```c #include <linux/module.h> #include <linux/platform_device.h> #include <linux/gpio/consumer.h> #include <linux/of.h> #include <linux/delay.h> struct mumbai_flash_data { struct gpio_desc *enable_gpio; // 使能GPIO描述符 }; static int mumbai_flash_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct mumbai_flash_data *data; int ret; // 分配设备私有数据 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; // 获取使能GPIO(从设备树) data->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_HIGH); if (IS_ERR(data->enable_gpio)) { ret = PTR_ERR(data->enable_gpio); dev_err(dev, "Failed to get enable GPIO: %d\n", ret); return ret; } // 可选:动态控制GPIO(例如初始化时序) gpiod_set_value(data->enable_gpio, 0); // 先拉低 msleep(10); // 延时10ms gpiod_set_value(data->enable_gpio, 1); // 再拉高 platform_set_drvdata(pdev, data); dev_info(dev, "Mumbai flashlight GPIO initialized (HIGH)\n"); return 0; } static int mumbai_flash_remove(struct platform_device *pdev) { struct mumbai_flash_data *data = platform_get_drvdata(pdev); // 移除时拉低GPIO(安全关闭) if (data->enable_gpio) gpiod_set_value(data->enable_gpio, 0); dev_info(&pdev->dev, "Mumbai flashlight GPIO removed\n"); return 0; } static const struct of_device_id mumbai_flash_of_match[] = { { .compatible = "mediatek,strobe_main" }, // 必须与设备树compatible匹配 { } }; MODULE_DEVICE_TABLE(of, mumbai_flash_of_match); static struct platform_driver mumbai_flash_driver = { .probe = mumbai_flash_probe, .remove = mumbai_flash_remove, .driver = { .name = "mumbai-flashlight", .of_match_table = mumbai_flash_of_match, }, }; module_platform_driver(mumbai_flash_driver); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Mumbai Flashlight GPIO Control Driver"); MODULE_LICENSE("GPL"); ``` ### 关键点说明 1. **设备树修改**: - 添加 `enable-gpios = <&pio 123 GPIO_ACTIVE_HIGH>` 指定使能GPIO。 - `gpio-initial-state = "high"` 确保初始状态为高电平(也可通过驱动代码的 `GPIOD_OUT_HIGH` 实现)。 2. **驱动功能**: - 使用 `devm_gpiod_get()` 获取GPIO资源,参数 `GPIOD_OUT_HIGH` 设置初始输出高电平。 - 示例中包含初始化时序(先拉低再拉高),可根据硬件需求调整。 3. **兼容性**: - 驱动通过 `compatible = "mediatek,strobe_main"` 匹配设备树节点。 ### 验证方法 1. **检查设备树加载**: ```bash cat /proc/device-tree/i2c6/flashlights_mumbai@63/enable-gpios ``` 2. **查看GPIO状态**: ```bash gpiodetect | grep 123 # 确认GPIO123是否存在 gpioinfo | grep 123 # 查看当前电平 ``` 3. **动态控制测试**(如实现sysfs接口): ```c // 在驱动中添加(可选): static ssize_t enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct mumbai_flash_data *data = dev_get_drvdata(dev); int val; if (kstrtoint(buf, 10, &val)) return -EINVAL; gpiod_set_value(data->enable_gpio, !!val); return count; } static DEVICE_ATTR_WO(enable); ``` ### 扩展问题(
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值