241 struct my_conftype *conf = (structmy_conftype *) config; 242
243 switch (conf) {
244 case PLATFORM_X_PULL_UP: 245 ... 246 } 247 } 248} 249
250static int foo_pin_config_group_get (struct pinctrl_dev *pctldev, 251 unsigned selector, 252 unsigned long *config) 253{ 254 ... 255} 256
257static int foo_pin_config_group_set (struct pinctrl_dev *pctldev, 258 unsigned selector, 259 unsigned long config) 260{ 261 ... 262} 263
264static struct pinconf_opsfoo_pconf_ops = { 265 .pin_config_get = foo_pin_config_get, 266 .pin_config_set = foo_pin_config_set,
267 .pin_config_group_get =foo_pin_config_group_get, 268 .pin_config_group_set =foo_pin_config_group_set, 269}; 270
271/* Pin config operations are handled by some pin controller */ 272static struct pinctrl_descfoo_desc = { 273 ...
274 .confops = &foo_pconf_ops, 275};
其中的pin_config_group_get()、pin_config_group_set()针对的是可同时配置一个引脚组的状态情况,而pin_config_get()、pin_config_set()针对的则是单个引脚的配置。
与GPIO子系统的交互
pinctrl驱动中所覆盖的引脚可能同时可作为GPIO用,内核的GPIO子系统和pinctrl子系统本来是并行工作的,但是有时候需要交叉映射,这种情况下,需要在pinctrl驱动中告知pinctrl子系统核心层GPIO与底层pinctrl驱动所管理的引脚之间的映射关系。假设pinctrl驱动中定义的引脚32~47与gpio_chip实例chip_a的GPIO对应,引脚64~71与gpio_chip实例chip_b的GPIO对应,即映射关系为: chip a:
- GPIO range :[32 .. 47] - pinrange : [32 .. 47] chip b:
- GPIO range :[48 .. 55] - pinrange : [64 .. 71]
则在特定pinctrl驱动中可以透过如下代码注册2个GPIO范围: 305struct gpio_chip chip_a; 306struct gpio_chip chip_b; 307
308static struct pinctrl_gpio_range gpio_range_a = { 309 .name = \310 .id = 0, 311 .base = 32, 312 .pin_base = 32, 313 .npins = 16, 314 .gc = &chip_a; 315}; 316
317static struct pinctrl_gpio_range gpio_range_b = { 318 .name = \319 .id = 0, 320 .base = 48, 321 .pin_base = 64, 322 .npins = 8, 323 .gc = &chip_b; 324}; 325 326{
327 struct pinctrl_dev *pctl; 328 ...
329 pinctrl_add_gpio_range(pctl,&gpio_range_a); 330 pinctrl_add_gpio_range(pctl,&gpio_range_b);
331}
在基于内核gpiolib的GPIO驱动中,若设备驱动需进行GPIO申请gpio_request()和释放gpio_free(),GPIO驱动则会调用pinctrl子系统中的pinctrl_request_gpio()和pinctrl_free_gpio()通用API,pinctrl子系统会查找申请的GPIO和pin的映射关系,并确认引脚是否被其他复用功能所占用。与pinctrl子系统通用层pinctrl_request_gpio()和pinctrl_free_gpio()API对应,在底层的具体pinctrl驱动中,需要实现pinmux_ops结构体的gpio_request_enable()和gpio_disable_free()成员函数。
除了gpio_request_enable()和gpio_disable_free()成员函数外,pinmux_ops结构体主要还用来封装pinmux功能enable/disable的callback函数,下面可以看到它更多的细节。 引脚复用(pinmux)
pinctrl驱动中可处理引脚复用,它定义了FUNCTIONS(功能),驱动可以设置某FUNCTIONS的enable或者disable。各个FUNCTIONS联合起来组成一个一维数组,譬如{ spi0, i2c0, mmc0 }就描述了3个不同的FUNCTIONS。 一个特定的功能总是要求一些引脚组(pingroup)来完成,引脚组的数量为可以为1个或者多个。假设对前文所描述的PGA封装的SoC而言,如下图: 387
388 A B C D E F G H 389 +---+
390 8 | o | o o o o o o o 391 | |
392 7 | o | o o o o o o o 393 | |
394 6 | o | o o o o o o o 395 +---+---+
396 5 | o | o | o o o o o o 397 +---+---+ +---+ 398 4 o o o o o o | o | o 399 | | 400 3 o o o o o o | o | o 401 | | 402 2 o o o o o o | o | o 403 +-------+-------+-------+---+---+ 404 1 | o o| o o | o o | o | o | 405 +-------+-------+-------+---+---+
I2C功能由{ A5, B5 }引脚组成,而在定义引脚描述的pinctrl_pin_desc结构体实例foo_pins的时候,将它们的序号定义为了{ 24, 25 } ;而SPI功能则由可以由{ A8, A7, A6, A5 }和 { G4, G3, G2, G1 }, 也即{ 0, 8, 16, 24 }和{ 38, 46, 54, 62 }两个引脚组完成(注意在整个系统中,引脚组的名字不会重叠)。
由此,功能和引脚组的组合就可以决定一组引脚在系统里的作用,因此在设置某组引脚的作用时,pinctrl的核心层会将功能的序号以及引脚组的序号传递给底层pinctrl驱动中相关的callback函数。
在整个系统中,驱动或板级代码调用pinmux相关的API获取引脚后,会形成一个(pinctrl、使用引脚的设备、功能、引脚组)的映射关系,假设在某电路板上,将让spi0 设备使用pinctrl0的fspi0功能以及gspi0引脚组,让i2c0设备使用pinctrl0的fi2c0功能和gi2c0引脚组,我们将得到如下的映射关系: 502 {
503 {\504 {\505 }
pinctrl子系统的核心会保证每个引脚的排他性,因此一个引脚如果已经被某设备用掉了,而其他的设备又申请该引脚行驶其他的功能或GPIO,则pinctrl核心层会让该次申请失败。
特定pinctrl驱动中pinmux相关的代码主要处理如何enable/disable某一{功能,引脚组}的组合,譬如,当spi0设备申请pinctrl0的fspi0功能和gspi0引脚组以便将gspi0引脚组配置为SPI接口时,相关的callback被组织进一个pinmux_ops结构体,而该结构体的实例最终成为前文pinctrl_desc的pmxops成员: 562#include 563#include 564
565struct foo_group { 566 const char *name; 567 const unsigned int *pins; 568 const unsigned num_pins; 569}; 570
571static const unsigned spi0_0_pins[] = { 0, 8, 16, 24 }; 572static const unsigned spi0_1_pins[] = { 38, 46, 54, 62 }; 573static const unsigned i2c0_pins[] = { 24, 25 }; 574static const unsigned mmc0_1_pins[] = { 56, 57 }; 575static const unsigned mmc0_2_pins[] = { 58, 59 }; 576static const unsigned mmc0_3_pins[] = { 60, 61, 62, 63 }; 577
578static const struct foo_group foo_groups[] = { 579 {
580 .name =\581 .pins = spi0_0_pins,
582 .num_pins =ARRAY_SIZE(spi0_0_pins), 583 }, 584 {
585 .name =\586 .pins = spi0_1_pins,
587 .num_pins = ARRAY_SIZE(spi0_1_pins),
588 }, 589 {
590 .name = \591 .pins = i2c0_pins,
592 .num_pins =ARRAY_SIZE(i2c0_pins), 593 }, 594 {
595 .name =\596 .pins = mmc0_1_pins,
597 .num_pins =ARRAY_SIZE(mmc0_1_pins), 598 }, 599 {
600 .name =\601 .pins = mmc0_2_pins,
602 .num_pins =ARRAY_SIZE(mmc0_2_pins), 603 }, 604 {
605 .name =\606 .pins = mmc0_3_pins,
607 .num_pins =ARRAY_SIZE(mmc0_3_pins), 608 }, 609}; 610 611
612static int foo_get_groups_count(struct pinctrl_dev *pctldev) 613{
614 return ARRAY_SIZE(foo_groups); 615} 616
617static const char *foo_get_group_name(struct pinctrl_dev *pctldev, 618 unsigned selector) 619{
620 return foo_groups[selector].name; 621} 622
623static int foo_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, 624 unsigned **const pins,