tiny4412 设备树之pinctrl(番外)
来源:互联网 发布:电玩游戏平台源码 编辑:程序博客网 时间:2024/05/21 06:49
开发板:tiny4412(1611)
内核:linux4.4
编译器: arm-none-linux-gnueabi-gcc (gcc version 4.8.3 20140320)
许多Soc内部都包含pin控制器,通过pin控制器的寄存器,我们可以配置一个或者一组引脚的功能和特性。
在软件方面,linux内核中提供了pinctrl子系统,目的是为了统一各SoC厂商的pin脚管理,避免各SoC厂商各自实现相同的pin脚管理子系统,减少SoC厂商系统移植工作量。
通过pinctrl驱动可以操作pin控制器,完成如下工作:
1. 枚举并且命名pin控制器可控制的所有引脚;
2. 提供引脚的复用能力;
3. 提供配置引脚的能力,如驱动能力、上拉下拉和数据属性等;
下面以配置使用一个IO口,来介绍pinctrl的使用。
在设备树根节点添加如下信息:
(gpj属于pinctrl_0)&pinctrl_0{ gpio_in: gpj1_3in{ samsung,pins = "gpj1-3"; samsung,pin-function = <0>; samsung,pin-pud = <0>; samsung,pin-drv = <0>; }; gpio_out: gpj1_3out{ samsung,pins = "gpj1-3"; samsung,pin-function = <1>; samsung,pin-pud = <0>; samsung,pin-drv = <0>; };};PS: samsung,pin-function、samsung,pin-pud、samsung,pin-drv实际上是SOC厂商对寄存器配置的封装。
在设备树上引用pinctrl子节点:
demo@11400260{ compatible ="gpio_j1-3"; reg = <0x11400260 0x14>; tiny4412,demo =<&gpj1 3 GPIO_ACTIVE_HIGH>; pinctrl-names = "in","out"; pinctrl-0 = <&gpio_in>; pinctrl-1 = <&gpio_out>; };
驱动中解析配置所需API:
//申请引脚pin=of_get_named_gpio(dev->of_node,"tiny4412,demo",0);devm_gpio_request_one(dev,pin,GPIOF_OUT_INIT_HIGH,"gpj1_3");//配置状态pctrl=devm_pinctrl_get(dev);psate_in=pinctrl_looup_state(pctrl,"in");pinctrl_select_state(pin,psate_in);//读写IOgpio_set_value(pin,voltage);gpio_get_value(pin);
驱动:
#include <linux/init.h>#include <linux/module.h>#include <linux/platform_device.h>#include <linux/gpio.h>#include <linux/of.h>#include <linux/of_gpio.h>#include <linux/interrupt.h>#include <linux/sched.h> #include <linux/cdev.h> #include <asm/uaccess.h>#include <linux/kdev_t.h>#include <linux/fs.h>#define dev_num 1struct device *dev;static struct pinctrl *pinctrl; static struct pinctrl_state *pinctrl_in;static struct pinctrl_state *pinctrl_out;static struct cdev gpj1_3_cdev;static struct class *gpj_class;static struct device *class_dev;static int major;static dev_t devid;static int gpj1_3_pin;static char devname[]="gpj_1_3";static int gpj1_3_open(struct inode * inode, struct file * file){ printk("%s enter.\n", __func__); devm_gpio_request_one(dev, gpj1_3_pin,GPIOF_OUT_INIT_HIGH,"gpj1-3"); pinctrl=devm_pinctrl_get(dev); pinctrl_out=pinctrl_lookup_state(pinctrl,"out"); pinctrl_in=pinctrl_lookup_state(pinctrl,"in"); return 0;}static ssize_t gpj1_3_read(struct file *file, char __user *to, size_t count, loff_t *off){ int voltage; printk("%s enter.\n", __func__); pinctrl_select_state(pinctrl,pinctrl_in); voltage=gpio_get_value(gpj1_3_pin); copy_to_user(to,&voltage,sizeof(voltage)); return sizeof(voltage);}static ssize_t gpj1_3_write (struct file *file, const char __user *from, size_t count, loff_t *off){ int voltage; printk("%s enter.\n", __func__); pinctrl_select_state(pinctrl,pinctrl_out); copy_from_user(&voltage,from,sizeof(voltage)); gpio_set_value(gpj1_3_pin,voltage); return sizeof(voltage);}static int gpj1_3_release(struct inode *inode, struct file *file){ devm_gpio_free(dev,gpj1_3_pin); return 0;}static const struct file_operations gpj1_3_fops={ .owner = THIS_MODULE, .open = gpj1_3_open, .read = gpj1_3_read, .write = gpj1_3_write, .release = gpj1_3_release, }; static int pinctrl_probe(struct platform_device *pdev) { int error; dev = &pdev->dev; printk("%s enter.\n", __func__); if (!dev->of_node) { dev_err(dev, "no platform data.\n"); goto err0; } gpj1_3_pin=of_get_named_gpio(dev->of_node,"tiny4412,demo",0); error=alloc_chrdev_region(&devid, 0, dev_num, "gpj1_3"); if(error){ dev_err(dev, "alloc region failed.\n"); goto err0; } major = MAJOR(devid); cdev_init(&gpj1_3_cdev, &gpj1_3_fops); cdev_add(&gpj1_3_cdev, MKDEV(major, 0), dev_num); gpj_class=class_create(THIS_MODULE,"gpj_1_3"); class_dev=device_create(gpj_class, NULL, devid, NULL, devname); return 0;err0: return -EINVAL;}static int pinctrl_remove(struct platform_device *pdev) { printk("%s enter.\n", __func__); unregister_chrdev_region(devid,dev_num); cdev_del(&gpj1_3_cdev); device_destroy(gpj_class,MKDEV(major, 0)); class_destroy(gpj_class); return 0;}static const struct of_device_id dt_ids[] = { { .compatible = "gpio_j1-3", }, {},};MODULE_DEVICE_TABLE(of, dt_ids);static struct platform_driver pinctrl_driver = { .driver = { .name = "gpj1_3", .of_match_table = of_match_ptr(dt_ids), }, .probe = pinctrl_probe, .remove = pinctrl_remove,};static int pinctrl_init(void){ int ret; printk("%s enter.\n", __func__); ret = platform_driver_register(&pinctrl_driver); if (ret) printk(KERN_ERR "int demo: probe failed: %d\n", ret); return ret;}static void pinctrl_exit(void){ printk("%s enter.\n", __func__); platform_driver_unregister(&pinctrl_driver);}module_init(pinctrl_init);module_exit(pinctrl_exit);MODULE_LICENSE("GPL");
测试程序:
include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>int main(){ int fd; int i; fd=open("/dev/gpj_1_3",O_RDWR); while(1){ i=0; write(fd,&i,sizeof(i)); sleep(1); i=1; write(fd,&i,sizeof(i)); sleep(1); } return 0;}
阅读全文
0 0
- tiny4412 设备树之pinctrl(番外)
- tiny4412 设备树之i2c设备(二)
- tiny4412 设备树之按键中断(一)
- tiny4412 设备树之SD卡驱动(三)
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6设备树pinctrl解析
- imx6ul设备树pinctrl解析
- tiny4412学习(四)之移植linux-设备树(2)设备树之LED点灯
- tiny4412学习(四)之移植linux-设备树(1)设备树基础知识及GPIO中断
- linux设备树中pinctrl的配置(上)
- linux设备树中pinctrl的配置(下)
- jQuery EasyUI弹出确认对话框(确认操作中.....)
- 风控分类模型种类(决策、排序)比较与模型评估体系(ROC/gini/KS/lift)
- 使用PyCharm执行scrapy项目
- IE浏览器被2345网址导航劫持
- 初见Spring之JDBC
- tiny4412 设备树之pinctrl(番外)
- 磁盘分区
- 扩展欧几里德板子 poj2142
- FZU 2082 过路费(树链剖分,边权)
- Tomcat的访问日志-localhost_access_log和记录Post请求参数
- 网页更容易被搜索引擎收录--善用标签
- 集合,增删改查,事务
- Javascript怎么将秒转换为时间
- Mathematica