北京网站备案号查询,网站建设doc,最大的中文搜索引擎,宝安中心医院妇科1、STM32MP1的pinctrl子系统驱动
pinctrl子系统源码目录为drivers/pinctrl#xff0c;一个PIN最好只能被一个外设使用。
“stm32mp151.dtsi”中有一个“pin-controller节点标签”叫pinctrl
pinctrl: pin-controller50002000 {
#address-cells 1;
/*定义子节点的…1、STM32MP1的pinctrl子系统驱动
pinctrl子系统源码目录为drivers/pinctrl一个PIN最好只能被一个外设使用。
“stm32mp151.dtsi”中有一个“pin-controller节点标签”叫pinctrl
pinctrl: pin-controller50002000 {
#address-cells 1;
/*定义子节点的reg和ranges的addres长度为32个位*/
#size-cells 1;
/*定义子节点的reg和ranges的length长度为32个位*/
compatible st,stm32mp157-pinctrl;
/*compatible属性用于将设备和驱动绑定起来*/
ranges 0 0x50002000 0xa400; /*子节点寄存器起始地址为0*/
/*父节点寄存器起始地址为0x50002000*/
/*寄存器最大偏移地址为0xa400*/
interrupt-parent exti;
st,syscfg exti 0x60 0xff;
hwlocks hsem 0 1;
pins-are-numbered; gpioa: gpio50002000 { /*子节点gpio起始地址为0x50002000*/
gpio-controller;
#gpio-cells 2;
/*定义描述使用一个gpio口需要提供2个指定的参数*/
interrupt-controller;
#interrupt-cells 2;
reg 0x0 0x400;
/*reg属性的值:当前节点寄存器起始地址为0长度为0x400*/
clocks rcc GPIOA;
st,bank-name GPIOA;
status disabled;
}; gpiob: gpio50003000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
/*表明引用这个中断控制器需要2个cell*/
/*一个是使用哪个中断另外一个是中断触发类型*/
reg 0x1000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x1000长度为0x400*/
clocks rcc GPIOB;
st,bank-name GPIOB;
status disabled;
}; gpioc: gpio50004000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x2000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x2000长度为0x400*/
clocks rcc GPIOC;
st,bank-name GPIOC;
status disabled;
}; gpiod: gpio50005000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x3000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x3000长度为0x400*/
clocks rcc GPIOD;
st,bank-name GPIOD;
status disabled;
}; gpioe: gpio50006000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x4000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x4000长度为0x400*/
clocks rcc GPIOE;
st,bank-name GPIOE;
status disabled;
}; gpiof: gpio50007000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x5000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x5000长度为0x400*/
clocks rcc GPIOF;
st,bank-name GPIOF;
status disabled;
}; gpiog: gpio50008000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x6000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x6000长度为0x400*/
clocks rcc GPIOG;
st,bank-name GPIOG;
status disabled;
}; gpioh: gpio50009000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x7000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x7000长度为0x400*/
clocks rcc GPIOH;
st,bank-name GPIOH;
status disabled;
}; gpioi: gpio5000a000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x8000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x8000长度为0x400*/
clocks rcc GPIOI;
st,bank-name GPIOI;
status disabled;
}; gpioj: gpio5000b000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0x9000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0x9000长度为0x400*/
clocks rcc GPIOJ;
st,bank-name GPIOJ;
status disabled;
}; gpiok: gpio5000c000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0xa000 0x400;
/*reg属性的值:当前节点寄存器起始地址为0xa000长度为0x400*/
clocks rcc GPIOK;
st,bank-name GPIOK;
status disabled;
};
}; pinctrl_z: pin-controller-z54004000 {
#address-cells 1;
#size-cells 1;
compatible st,stm32mp157-z-pinctrl;
ranges 0 0x54004000 0x400; /*子节点寄存器起始地址为0*/
/*父节点寄存器起始地址为0x50004000*/
/*寄存器最大偏移地址为0x400*/
pins-are-numbered;
interrupt-parent exti;
st,syscfg exti 0x60 0xff;
hwlocks hsem 0 1; gpioz: gpio54004000 {
gpio-controller;
#gpio-cells 2;
interrupt-controller;
#interrupt-cells 2;
reg 0 0x400;
/*reg属性的值:当前节点寄存器起始地址为0长度为0x400*/
clocks scmi0_clk CK_SCMI0_GPIOZ;
st,bank-name GPIOZ;
st,bank-ioport 11;
status disabled;
};
};
stm32mp15-pinctrl.dtsi中有一个pinctrl节点
pinctrl { /*pinctrl为节点名称*/
adc1_in6_pins_a: adc1-in6 { /*adc1-in6为设备名*/
pins {
pinmux STM32_PINMUX(F, 12, ANALOG); /*GPIOF12用做AD输入口*/
};
}; m_can1_pins_a: m-can1-0 {
pins1 {
pinmux STM32_PINMUX(H, 13, AF9); /* GPIOH13用作CAN1_TX */
slew-rate 1;
drive-push-pull;/*推挽输出*/
bias-disable;/*禁止使用内部偏置电压*/
};
pins2 {
pinmux STM32_PINMUX(I, 9, AF9); /*GPIOI9用作CAN1_RX */
bias-disable;/*禁止使用内部偏置电压*/
};
}; uart4_pins_a: uart4-0 {
pins1 {
pinmux STM32_PINMUX(G, 11, AF6); /*GPIOG11用作UART4_TX */
bias-disable;/*禁止使用内部偏置电压*/
drive-push-pull;/*推挽输出*/
slew-rate 0;
};
pins2 {
pinmux STM32_PINMUX(B, 2, AF8); /*GPIOB2用作UART4_RX */
bias-disable;/*禁止使用内部偏置电压*/
};
}; uart4_pins_b: uart4-1 {
pins1 {
pinmux STM32_PINMUX(D, 1, AF8); /* GPIOD1用作UART4_TX */
bias-disable; /*禁止使用内部偏置电压*/
drive-push-pull; /*推挽输出*/
slew-rate 0;
};
pins2 {
pinmux STM32_PINMUX(B, 2, AF8); /* GPIOB2用作UART4_RX */
bias-disable;/*禁止使用内部偏置电压*/
};
}; pwm1_pins_a: pwm1-0 {
pins {
pinmux STM32_PINMUX(E, 9, AF1), /* GPIOE9用作TIM1_CH1 */ STM32_PINMUX(E, 11, AF1), /*GPIOE11用作TIM1_CH2 */ STM32_PINMUX(E, 14, AF1); /* GPIOE14用作TIM1_CH4 */
bias-pull-down;/*内部下拉*/
drive-push-pull;/*推挽输出*/
slew-rate 0;
};
};
}; 2、gpio子系统提供的常用API函数
需要包含头文件#include linux/gpio.h
1)、申请“gpio编号”
int gpio_request(unsigned gpio, const char *label)
gpio要申请的“gpio编号”
Iabel给这个gpio引脚设置个名字为label所指向的字符串
返回值0申请“gpio编号”成功;其他值申请“gpio编号”失败
注意GPIOA有16个引脚因此GA0的“gpio编号”为0GA15的“gpio编号”为15GPIOB有16个引脚因此GB0的“gpio编号”为16GB15的“gpio编号”为31GPIOC有16个引脚因此GC0的“gpio编号”为32GC15的“gpio编号”为47等等以此类推 2)、释放“gpio编号”
void gpio_free(unsigned gpio)
gpio要释放的“gpio编号” struct MyGpioLED_dev{ dev_t devid; /*声明32位变量devid用来给保存设备号 */ int major; /* 主设备号 */ int minor; /* 次设备号 */ struct cdev cdev; /*字符设备结构变量cdev */ struct class *class; /* 类 */ struct device *device;/*设备*/ struct device_node *nd;/* 设备节点 */ int led_gpio; /* led所使用的GPIO编号 */
};
struct MyGpioLED_dev strMyGpioLED;
int ret;
strMyGpioLED.nd of_find_node_by_path(/gpio_led);
//path/gpio_led使用“全路径的节点名“在“stm32mp157d-atk.dts“中查找节点“gpio_led”
//返回值:返回找到的节点如果为NULL表示查找失败。
if(strMyGpioLED.nd NULL) { printk(gpio_led node not find!\r\n); return -EINVAL;
} strMyGpioLED.led_gpio of_get_named_gpio(strMyGpioLED.nd, led-gpio, 0); //在gpio_led节点中led-gpio gpioi 0 GPIO_ACTIVE_LOW //npstrMyGpioLED.nd,指定的“设备节点” //propnameled-gpio给定要读取的属性名字 //Index0,给定的GPIO索引为0 //返回值正值获取到的GPIO编号负值失败。
if(strMyGpioLED.led_gpio 0) { printk(cant get led-gpio); return -EINVAL; }
printk(led-gpio num %d\r\n, strMyGpioLED.led_gpio); //打印结果为“led-gpio num 128“ //因为GPIO编号是从0开始的GPIOI端口的序号是8每个端口有16个IO口因此GPIOI0的编号为8*1612 ret gpio_request(strMyGpioLED.led_gpio, LED-GPIO); //gpiostrMyGpioLED.led_gpio指定要申请的“gpio编号” //IabelLED-GPIO给这个gpio引脚设置个名字为LED-GPIO //返回值0申请“gpio编号”成功;其他值申请“gpio编号”失败
if (ret) { printk(KERN_ERR strMyGpioLED: Failed to request led-gpio\n); return ret; } gpio_free(strMyGpioLED.led_gpio);//释放“gpio编号” 3)、设置“某个GPIO为输入口”
int gpio_direction_input(unsigned gpio)
gpio要设置为输入的“gpio编号”
返回值0设置“某个GPIO为输入口”成功;负值设置“某个GPIO为输入口”失败。 4)、设置“某个GPIO为输出口”
int gpio_direction_output(unsigned gpio, int value)
gpio要设置为输出的“gpio编号”
ValueGPIO 默认输出值 返回值0设置“某个GPIO为输出口”成功;负值设置“某个GPIO为输出口”失败。 5)、读取某个gpio口的值
#define gpio_get_value __gpio_get_value
int __gpio_get_value(unsigned gpio)
gpio要获取的“gpio编号”
返回值非负值返回“gpio口的值”;负值获取“gpio口的值”失败。 6)、设置gpio口的值为value
#define gpio_set_value __gpio_set_value
void __gpio_set_value(unsigned gpio, int value)
gpio要设置的“gpio编号”
Value要设置的值
举例
struct MyGpioLED_dev{ dev_t devid; /*声明32位变量devid用来给保存设备号 */ int major; /* 主设备号 */ int minor; /* 次设备号 */ struct cdev cdev; /*字符设备结构变量cdev */ struct class *class; /* 类 */ struct device *device;/*设备*/ struct device_node *nd;/* 设备节点 */ int led_gpio; /* led所使用的GPIO编号 */
};
struct MyGpioLED_dev strMyGpioLED;
int ret; strMyGpioLED.nd of_find_node_by_path(/gpio_led);
//path/gpio_led使用“全路径的节点名“在“stm32mp157d-atk.dts“中查找节点“gpio_led”
//返回值:返回找到的节点如果为NULL表示查找失败。
if(strMyGpioLED.nd NULL) { printk(gpio_led node not find!\r\n); return -EINVAL;
} strMyGpioLED.led_gpio of_get_named_gpio(strMyGpioLED.nd, led-gpio, 0); //在gpio_led节点中led-gpio gpioi 0 GPIO_ACTIVE_LOW //npstrMyGpioLED.nd,指定的“设备节点” //propnameled-gpio给定要读取的属性名字 //Index0,给定的GPIO索引为0 //返回值正值获取到的GPIO编号负值失败。
if(strMyGpioLED.led_gpio 0) { printk(cant get led-gpio); return -EINVAL; }
printk(led-gpio num %d\r\n, strMyGpioLED.led_gpio); //打印结果为“led-gpio num 128“ //因为GPIO编号是从0开始的GPIOI端口的序号是8每个端口有16个IO口因此GPIOI0的编号为8*1612
gpio_set_value(strMyGpioLED-led_gpio, 0); /* 打开LED灯 */ 3、与gpio相关的of函数
需要包含头文件#include linux/of_gpio.h 1)、根据给定的“设备节点”和“GPIO属性”统计GPIO的数量
int of_gpio_named_count(struct device_node *np, const char *propname)
np指定的“设备节点”。
propname要统计的GPIO属性。
返回值正值统计到的GPIO数量负值失败。 2)、根据给定的“设备节点”统计具有“gpios属性”的GPIO的数量
int of_gpio_count(struct device_node *np)
np指定的“设备节点”。
返回值正值返回具有“gpios属性”的GPIO的数量负值失败。 3)、根据给定的“设备节点”属性名和GPIO索引读取GPIO编号
int of_get_named_gpio(struct device_node *np, const char *propname, int index)
np指定的“设备节点”。
propname包含要获取GPIO信息的属性名
IndexGPIO索引因为一个属性里面可能包含多个GPIO此参数指定要获取哪个GPIO的编号如果只有一个GPIO信息的话此参数为0
返回值正值获取到的GPIO编号负值失败。
struct MyGpioLED_dev{ dev_t devid; /*声明32位变量devid用来给保存设备号 */ int major; /* 主设备号 */ int minor; /* 次设备号 */ struct cdev cdev; /*字符设备结构变量cdev */ struct class *class; /* 类 */ struct device *device;/*设备*/ struct device_node *nd;/* 设备节点 */ int led_gpio; /* led所使用的GPIO编号 */
};
struct MyGpioLED_dev strMyGpioLED;
int ret;
strMyGpioLED.nd of_find_node_by_path(/gpio_led);
//path/gpio_led使用“全路径的节点名“在“stm32mp157d-atk.dts“中查找节点“gpio_led”
//返回值:返回找到的节点如果为NULL表示查找失败。
if(strMyGpioLED.nd NULL) { printk(gpio_led node not find!\r\n); return -EINVAL;
} strMyGpioLED.led_gpio of_get_named_gpio(strMyGpioLED.nd, led-gpio, 0); //在gpio_led节点中led-gpio gpioi 0 GPIO_ACTIVE_LOW //npstrMyGpioLED.nd,指定的“设备节点” //propnameled-gpio给定要读取的属性名字 //Index0,给定的GPIO索引为0 //返回值正值获取到的GPIO编号负值失败。
if(strMyGpioLED.led_gpio 0) { printk(cant get led-gpio); return -EINVAL; }
printk(led-gpio num %d\r\n, strMyGpioLED.led_gpio); //打印结果为“led-gpio num 128“ //因为GPIO编号是从0开始的GPIOI端口的序号是8每个端口有16个IO口因此GPIOI0的编号为8*16128