linux查询引脚功能复用,Linux:使用pinctrl子系统动态切换复用pin脚的功能

Linux:使用pinctrl子系统动态切换复用pin脚的功能

Linux:使用pinctrl子系统动态切换复用pin脚的功能

Linux:使用pinctrl子系统动态切换复用pin脚的功能

一、许多soc内部都包含有pin控制器,通过pin控制器的寄存器,我们可以配置一个或者一组引脚的功能和特性。在软件方面,Linux内核提供了pinctrl子系统,目的是为了统一各soc厂商的pin脚管理。

7c071ea08b2af5a8bb8e86195e6d7db7.png

二、常用API介绍

1、struct pinctrl *devm_pinctrl_get(struct device *dev)

956ed3326c39621f880a58fd00f7a420.png

2、struct pinctrl_state *pinctrl_lookup_state(struct pinctrl *p,const char *name)

247258bd5f5a6fdb7520ce8cbfd94bf6.png

3、int pinctrl_select_state(struct pinctrl *p, struct pinctrl_state *state)

b0ce56a2901c72fc514e7cf04ee6f1d7.png

四、实例测试,动态切换i2c0和gpio功能

feed2bb2303c5f3df3ce2d9c5e4a3406.png

1、dts文件添加

gpio_i2c_exchage{

compatible= "gpio-i2c-exchage";

pinctrl-names= "default", "gpio";

pinctrl-0= ;

pinctrl-1= ;

};

i2c0_option{

i2c0_function: i2c0-function {

rockchip,pins =

<2 GPIO_D0 RK_FUNC_1 &pcfg_pull_none_smt>,

<2 GPIO_D1 RK_FUNC_1 &pcfg_pull_none_smt>;

};

i2c0_gpio: i2c0-gpio {

rockchip,pins =

<2 GPIO_D0 RK_FUNC_GPIO &pcfg_pull_none_smt>,

<2 GPIO_D1 RK_FUNC_GPIO &pcfg_pull_none_smt>;

};

};

2、测试driver代码kernel\drivers\char\pinctrl.c

#define pr_fmt(fmt) "%s:" fmt, __func__

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

struct pinctrl *i2c0_pinctrl;

struct pinctrl_state *i2c0_default;//uart

struct pinctrl_state *i2c0_gpio;//gpio

#define ROCKCHIP_GPIO_NR(bank, nr) (((bank)) * 32 + (nr))

#define I2C0_SCLKROCKCHIP_GPIO_NR(2,24)

const char *I2C0_PINCTRL_STATE_DEFAULT = "default";

const char *I2C0_PINCTRL_STATE_GPIO = "gpio";

static int biada_pinctrl_request_gpios(int state)

{

int result = 0;

if(state==0)

{

result = pinctrl_select_state(i2c0_pinctrl, i2c0_default);

if (result) {

printk("%s: Can not set %s pins\n",

__func__, "default");

}

}else

{

result = pinctrl_select_state(i2c0_pinctrl, i2c0_gpio);

if (result) {

printk("%s: Can not set %s pins\n",

__func__, "gpio");

}

}

printk(KERN_ERR "%s,request state(%s) ok, result = %d\n",

__func__, state ? "default" : "gpio",result);

return result;

}

static ssize_t pinctrl_show(struct device* cd,struct device_attribute *attr, char* buf)

{

ssize_t ret = 0;

sprintf(buf, "%s\n",__func__);

ret = strlen(buf) + 1;

return ret;

}

static ssize_t pinctrl_store(struct device* cd, struct device_attribute *attr,

const char* buf, size_t len)

{

unsigned long select = simple_strtoul(buf, NULL, 10);

printk("%s: %lu\n",__func__, select);

biada_pinctrl_request_gpios(select);

if(select)

{

printk("%s: set gpio low level\n", __func__);

gpio_direction_output(I2C0_SCLK, 0);

mdelay(100);

printk("%s: set gpio low high\n", __func__);

gpio_direction_output(I2C0_SCLK, 1);

}

return len;

}

static DEVICE_ATTR(biada_pinctrl,S_IRUGO | S_IWUSR, pinctrl_show, pinctrl_store);

static int biada_pinctrl_init(struct platform_device *pdata)

{

i2c0_pinctrl = devm_pinctrl_get(&pdata->dev);

printk("\n[************%s************devm_pinctrl_get]\n", __func__);

if (IS_ERR_OR_NULL(i2c0_pinctrl)) {

printk("Failed to get pin ctrl\n");

return PTR_ERR(i2c0_pinctrl);

}

// default

printk("\n[************%s************pinctrl_lookup_state i2c0_default]\n", __func__);

i2c0_default = pinctrl_lookup_state(i2c0_pinctrl,

I2C0_PINCTRL_STATE_DEFAULT);

if (IS_ERR_OR_NULL(i2c0_default)) {

printk("Failed to lookup pinctrl default state\n");

return PTR_ERR(i2c0_default);

}

// gpio

printk("\n[************%s************pinctrl_lookup_state i2c0_gpio]\n", __func__);

i2c0_gpio = pinctrl_lookup_state(i2c0_pinctrl,

I2C0_PINCTRL_STATE_GPIO);

if (IS_ERR_OR_NULL(i2c0_gpio)) {

printk("Failed to lookup pinctrl gpio state\n");

return PTR_ERR(i2c0_gpio);

}

printk("\n[************%s************]\n", __func__);

return 0;

}

// echo 0 >/sys/bus/platform/devices/gpio_i2c_exchage.35/biada_pinctrl //i2c0 mode

// echo 1 >/sys/bus/platform/devices/gpio_i2c_exchage.35/biada_pinctrl //gpio mode

static int biada_pinctrl_probe(struct platform_device *pdev)

{

int ret = 0;

biada_pinctrl_init(pdev);

if(device_create_file(&pdev->dev, &dev_attr_biada_pinctrl))

printk(KERN_ERR "Unable to createsysfs entry: '%s'\n",

dev_attr_biada_pinctrl.attr.name);

printk("\n[************%s************]\n", __func__);

return ret;

}

static int biada_pinctrl_remove(struct platform_device *plat)

{

return 0;

}

static struct of_device_id __attribute__ ((unused)) biada_pinctrl_of_match[] = {

{ .compatible = "gpio-i2c-exchage", },

{}

};

static struct platform_driver biada_pinctrl_driver = {

.probe = biada_pinctrl_probe,

.remove = biada_pinctrl_remove,

.driver = {

.name = "gpio-exchage",

.owner = THIS_MODULE,

.of_match_table = of_match_ptr(biada_pinctrl_of_match),

},

};

static int __init biada_init(void)

{

return platform_driver_register(&biada_pinctrl_driver);

}

static void __exit biada_exit(void)

{

platform_driver_unregister(&biada_pinctrl_driver);

}

MODULE_LICENSE("GPLv2");

MODULE_AUTHOR("trump, [email protected]");

MODULE_DESCRIPTION("Driver for Rockchip I2C Bus");

MODULE_VERSION("2.0");

module_init(biada_init);

module_exit(biada_exit);

3、运行结果效果如下,可以动态在i2c和gpio之间切换,用示波器测试gpio有波形,i2c可以work。

a3b158746b87b0ff002e1e11c9af9275.png

Linux:使用pinctrl子系统动态切换复用pin脚的功能相关教程

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值