Use pinctrl subsystem

A, pinctrl device tree configuration subsystem

  With pinctrl subsystem after the drive can operate pinctrl subsystem interface function complete I / O operations, and without the need to configure themselves. General pinctrl subsystem is driven by the BSP engineers to achieve good chip original. Drive engineers to use pinctrl subsystem configured device tree. Some I / O port has a different status (state), such that when a working group of I / O port is configured to uart interface configured to sleep when the output is high and the GPIO interface. pinctrl subsystem configured device tree also comply with service and client structure.

For example: where the node device to become a client subsystem pinctrl device, since it uses a pinctrl subsystem which provides interfaces out. pinctrl is the abbreviation of pincontroller.

// Client Node 
Device { 
    pinctrl -names = " default " , " SLEEP " ; // use pinctrl-names to indicate the status (state) of the device, there are two, respectively, the default state and a sleep state. 
    pinctrl- 0 = <& state_0_node_a>; // 0 states correspond to the "default" state, the corresponding pin is defined inside pinctrl-0. 
    pinctrl- 0 = <& state_1_node_a>; // first state corresponds to a "sleep" state, the corresponding pin is defined inside pinctrl-1. 
}; 

// -Service node 
pincontroller { 
    state_0_node_a { 
        function = " UART0 " ;
        u0rxtx", "u0rtscts";
    };
    state_1_node_a {
        function = "gpio";
        groups = "u0rxtx", "u0rtscts";
    };
};

  The above is a set of pins multiplexed, multiplexed in different states uart gpio pin or pins, known as "Generic pin multiplexing node" ( multiplex nodes ). Another configuration is called "Generic pin configuration node" ( configuration node ) is arranged on the pins, the different states (default, idle, sleep ...) arranged different functions.

An example of a configuration of the nodes as follows:

// Client Node 
Device { 
    pinctrl -names = " default " , " SLEEP " ; // use pinctrl-names to indicate the status (state) of the device, there are two, respectively, the default state and a sleep state. 
    pinctrl- 0 = <& state_0_node_a>; // 0 states correspond to the "default" state, the corresponding pin is defined inside pinctrl-0. 
    pinctrl- 0 = <& state_1_node_a>; // first state corresponds to a "sleep" state, the corresponding pin is defined inside pinctrl-1. 
}; 

// -Service node, controller to provide services 
pincontroller { 
    state_0_node_a { // multiplex node 
        function = " UART0 "Groups = " u0rxtx " , " u0rtscts " ; 
    }; 
    state_1_node_a { // Configure Node 
        Groups = " u0rxtx " , " u0rtscts " ; 
        Output -high; // output high 
    }; 
};

  Whether multiplex configuration node or nodes, are to operate these pins. It can be specified for a plurality of client state (state), corresponding to a child node can be specified in each of the states to describe its state. In the service-side child node controller implemented, it may be a child node can also be a complex configuration node (corresponding to the pin is configured as a state) with a node (the pin is multiplexed with corresponding to a function).

  For the client node, which is written in the device tree format is essentially the same, uniform. But for writing controller node on the service side of the five law eight, and some simply do not function and the group, the format can say is no.

A few examples of practical use:

1.imx6ull of

// Client side: 
@ {UART1 
    pinctrl -names = " default " ; 
    pinctrl - 0 = <& pinctrl_uart1> ; 
    Status = " Okay " ; 
}; 

// pincontroller server 
pinctrl_uart1: uartlgrp { 
    fsl.pins = <MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX, // named UART1_TX pins are multiplexed into UART1_DCE_TX function. 
        MX6UL_PAD_UART1_RX_DATA__UART1_DCE_RX>; // write here are two macros, so do not add "&" 
};

2.rk3288 platform

// Client terminal 
@ UART0 { 
    pinctrl -names = " default " ; 
    pinctrl - 0 = <& uart0_xfer & uart0_cts & uart0_rts>; // it uses three nodes to represent three pins. 
    = Status " Okay " ; 
}; 

// pincontroller server 
gpio4_uart0 { 
    uart0_xfer: UART0 - XFER { 
        rockchip, pins = <UART0BT_SIN>, <UART0BT_SOUT>; // use rockchip, pins used to specify which pins, it is equivalent to Groups 
        Rockchip, pull = <VALUE_PULL_DISABLE>; // these two fields to configure the parameters of these pins 
        rockchip, drive = <; 
    }; 
    Uart0_cts: UART0 - CTS { 
        Rockchip, pins = <UART0BT_CTSN>; // write here are two macro, there is no increase, "&", designated here actually two pins. 
        Rockchip, pull = <VALUE_PULL_DISABLE> ; 
        Rockchip, Drive = <VALUE_DRV_DEFAULT> ; 
    }; 
    uart0_rts: UART0 - RTS { 
        Rockchip, pins = <UART0BT_RTSN> ; 
        Rockchip, pull = <VALUE_PULL_DISABLE> ; 
        Rockchip, Drive = <VALUE_DRV_DEFAULT> ; 
    }; 
    uart0_rts_gpio: UART0 -rts- GPIO { 
        Rockchip, pins= <FUNC_TO_GPIO(UART0BT_RTSN)>;
        rockchip,drive = <VALUE_DRV_DEFAULT>;
    };
};

Although pincontroller server is no uniform format, but the notion that there is still the same, what to use pins that can be classified as a group of a group, these pins are multiplexed into a single function.

 

Second, how to use the drive subsystem pinctrl

  For how to use the driver code pinctrl subsystem, which is transparent to the driver engineers, we do not control the basic driving, when the device switches state (state pinctrl-names of the corresponding device tree), will be a corresponding pinctrl transfer.

1. Before the drive on the first probe to obtain a variety of state pinctl

really_probe // Drivers / Base / dd.c 
    / * the If the using pinctrl, now before the bind pins Probing * / 
    // first pin configuration acquisition pinctrl 
    RET = pinctrl_bind_pins (dev); // Drivers / Base / pinctrl.c
         // . 1 save "default" state of pin configuration 
        the dev-> pins-> default_state = pinctrl_lookup_state (the dev-> pins-> P, PINCTRL_STATE_DEFAULT);
         // 2. save "init" state of pin configuration 
        dev-> pins-> init_state = pinctrl_lookup_state (the dev-> pins-> P, PINCTRL_STATE_INIT);
         IF (IS_ERR (the dev-> pins-> init_state)) { // if the init state is present on the choice of "init" state, otherwise choose "default" state
            = pinctrl_select_state RET (the dev-> pins-> P, the dev-> pins-> default_state); 
        } the else { 
            RET = pinctrl_select_state (the dev-> pins-> P, the dev-> pins-> init_state); 
        } 
        // . 3. saving "sleep" state of pin configuration 
        the dev-> pins-> sleep_state = pinctrl_lookup_state (the dev-> pins-> P, PINCTRL_STATE_SLEEP);
         // 4. save "idle" state of pin configuration 
        dev-> pins-> idle_state = pinctrl_lookup_state (dev-> pins-> the p-, PINCTRL_STATE_IDLE);
     // then probe our drive 
    drv-> probe (dev);

2. If have to call their own, but also function

struct pinctrl * __must_check devm_pinctrl_get_select_default ( struct Device * dev) // Get pinctrl "default" state is disposed 
struct pinctrl * __must_check devm_pinctrl_get_select ( struct Device dev *, const  char * name); // Get the name specified configuration pinctrl 
void devm_pinctrl_put ( struct * the p-pinctrl); // release pinctrl allocation of resources, we usually do not need to call.

 

Guess you like

Origin www.cnblogs.com/hellokitty2/p/12501493.html