Linux芯片级移植与底层驱动(基于3.7.4内核)(6)

2019-03-10 13:53

voidgpio_free(unsigned gpio);

intgpio_direction_input(unsigned gpio);

intgpio_direction_output(unsigned gpio, int value);

intgpio_set_debounce(unsigned gpio, unsigned debounce); intgpio_get_value_cansleep(unsigned gpio);

voidgpio_set_value_cansleep(unsigned gpio, int value);

intgpio_request_one(unsigned gpio, unsigned long flags, const char *label); intgpio_request_array(const struct gpio *array, size_t num); voidgpio_free_array(const struct gpio *array, size_t num);

intdevm_gpio_request(struct device *dev, unsigned gpio, const char *label); intdevm_gpio_request_one(struct device *dev, unsigned gpio, unsigned long flags,const char *label);

voiddevm_gpio_free(struct device *dev, unsigned int gpio);

注意,内核中针对内存、IRQ、时钟、GPIO、pinctrl都有devm_开头的API,使用这部分API的时候,内核会有类似于Java资源自动回收机制,因此在代码中做出错处理时,无需释放相关的资源。

对于GPIO而言,特别值得一提的是,内核会创建/sys结点 /sys/class/gpio/gpioN/,透过它我们可以echo值从而改变GPIO的方向、设置和获取GPIO的值。

在拥有Device Tree支持的情况之下,我们可以透过Device Tree来描述某GPIO控制器提供的GPIO引脚被具体设备使用的情况。在GPIO控制器对应的结点中,需定义#gpio-cells 和gpio-controller属性,具体的设备结点则透过xxx-gpios属性来引用GPIO控制器结点及GPIO引脚。

如VEXPRESS电路板 DT文件arch/arm/boot/dts/vexpress-v2m.dtsi中拥有如下GPIO控制器结点: 73 v2m_sysreg:sysreg@00000 {

74 compatible =\75 reg = <0x000000x1000>; 76 gpio-controller; 77 #gpio-cells =<2>; 78 };

VEXPRESS电路板上的MMC控制器会使用该结点GPIO控制器提供的GPIO引脚,则具体的mmci@05000设备结点的会通过-gpios属性引用GPIO: 111 mmci@05000 {

112 compatible =\113 reg =<0x05000 x>; 114 interrupts =<9 >;

115 cd-gpios = < vm sysreg >; 116 wp-gpios =< vm sysreg >; 117 … 121 };

其中的cd-gpios用于SD/MMC卡的detection,而wp-gpios用于写保护,MMC主机控制器驱动会透过如下方法获取这2个GPIO,详见于drivers/mmc/host/mmci.c:

1220static void mmci_dt_populate_generic_pdata(struct device_node *np, 1221 structmmci_platform_data *pdata) 1222{

1223 int bus_width = 0; 1224

1225 pdata-

7. pinctrl驱动

许多SoC内部都包含pin控制器,通过pin控制器的寄存器,我们可以配置一个或者一组引脚的功能和特性。在软件上,Linux内核的pinctrl驱动可以操作pin控制器为我们完成如下工作: § 枚举并且命名pin控制器可控制的所有引脚; § 提供引脚复用的能力;

§ 提供配置引脚的能力,如驱动能力、上拉下拉、开漏(open drain)等。 pinctrl和引脚

在特定SoC的pinctrl驱动中,我们需要定义引脚。假设有一个PGA封装的芯片的引脚排布如下: A B C D E F G H 8 o o o o o o o o 7 o o o o o o o o 6 o o o o o o o o 5 o o o o o o o o 4 o o o o o o o o 3 o o o o o o o o 2 o o o o o o o o 1 o o o o o o o o

在pinctrl驱动初始化的时候,需要向pinctrl子系统注册一个pinctrl_desc描述符,在该描述符中包含所有引脚的列表。可以通过如下代码来注册这个pin控制器并命名其所有引脚: 59#include 60

61const struct pinctrl_pin_descfoo_pins[] = { 62 PINCTRL_PIN(0, \63 PINCTRL_PIN(1, \64 PINCTRL_PIN(2, \

65 ...

66 PINCTRL_PIN(61, \67 PINCTRL_PIN(62, \68 PINCTRL_PIN(63, \69}; 70

71static struct pinctrl_descfoo_desc = { 72 .name = \73 .pins = foo_pins,

74 .npins = ARRAY_SIZE(foo_pins), 75 .maxpin = 63,

76 .owner = THIS_MODULE, 77}; 78

79int __init foo_probe(void) 80{

81 struct pinctrl_dev *pctl; 82

83 pctl = pinctrl_register(&foo_desc,, NULL); 84 if (IS_ERR(pctl))

85 pr_err(\86}

引脚组(pin group)

在pinctrl子系统中,支持将一组引脚绑定为同一功能。假设{ 0, 8, 16, 24 }这一组引脚承担SPI的功能,而{ 24, 25 }这一组引脚承担I2C接口功能。在驱动的代码中,需要体现这个分组关系,并且为这些分组实现pinctrl_ops的成员函数get_groups_count、get_groups_count和get_groups_count,将pinctrl_ops填充到前文pinctrl_desc的实例foo_desc中。 130#include 131

132struct foo_group { 133 const char *name; 134 const unsigned int *pins; 135 const unsigned num_pins; 136}; 137

138static const unsigned int spi0_pins[] = { 0, 8, 16, 24 }; 139static const unsigned int i2c0_pins[] = { 24, 25 }; 140

141static const struct foo_group foo_groups[] = { 142 {

143 .name = \144 .pins = spi0_pins,

145 .num_pins =ARRAY_SIZE(spi0_pins), 146 }, 147 {

148 .name = \149 .pins = i2c0_pins,

150 .num_pins =ARRAY_SIZE(i2c0_pins), 151 }, 152}; 153 154

155static int foo_get_groups_count(struct pinctrl_dev *pctldev) 156{

157 return ARRAY_SIZE(foo_groups); 158} 159

160static const char *foo_get_group_name(struct pinctrl_dev *pctldev, 161 unsigned selector) 162{

163 return foo_groups[selector].name; 164} 165

166static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, 167 unsigned **const pins, 168 unsigned *const num_pins) 169{

170 *pins = (unsigned *) foo_groups[selector].pins; 171 *num_pins =foo_groups[selector].num_pins; 172 return 0; 173} 174

175static struct pinctrl_opsfoo_pctrl_ops = { 176 .get_groups_count =foo_get_groups_count, 177 .get_group_name = foo_get_group_name,

178 .get_group_pins = foo_get_group_pins, 179}; 180 181

182static struct pinctrl_descfoo_desc = { 183 ...

184 .pctlops = &foo_pctrl_ops, 185};

get_groups_count()成员函数用于告知pinctrl子系统该SoC中合法的被选引脚组有多少个,而get_group_name()则提供引脚组的名字,get_group_pins()提供引脚组的引脚表。在设备驱动调用pinctrl通用API使能某一组引脚的对应功能时,pinctrl子系统的核心层会调用上述callback函数。 引脚配置

设备驱动有时候需要配置引脚,譬如可能把引脚设置为高阻或者三态(达到类似断连引脚的效果),或通过某阻值将引脚上拉/下拉以确保默认状态下引脚的电平状态。驱动中可以自定义相应板级引脚配置API的细节,譬如某设备驱动可能通过如下代码将某引脚上拉: #include

ret= pin_config_set(\

其中的PLATFORM_X_PULL_UP由特定的pinctrl驱动定义。在特定的pinctrl驱动中,需要实现完成这些配置所需要的callback函数(pinctrl_desc的confops成员函数): 222#include 223#include

224#include \225

226static int foo_pin_config_get(struct pinctrl_dev *pctldev, 227 unsigned offset, 228 unsigned long *config) 229{

230 struct my_conftype conf; 231

232 ... Find setting for pin @ offset ... 233

234 *config = (unsigned long) conf; 235} 236

237static int foo_pin_config_set(struct pinctrl_dev *pctldev, 238 unsigned offset, 239 unsigned long config) 240{


Linux芯片级移植与底层驱动(基于3.7.4内核)(6).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:…生僻字相对大全…

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: