diff mbox

[1/4] pinctrl: Broadcom Cygnus pinctrl device tree binding

Message ID 1417131990-17954-2-git-send-email-rjui@broadcom.com (mailing list archive)
State New, archived
Headers show

Commit Message

Ray Jui Nov. 27, 2014, 11:46 p.m. UTC
Device tree binding documentation for Broadcom Cygnus pinctrl driver

Signed-off-by: Ray Jui <rjui@broadcom.com>
Reviewed-by: Scott Branden <sbranden@broadcom.com>
---
 .../bindings/pinctrl/brcm,cygnus-pinctrl.txt       |   92 ++++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt

Comments

Linus Walleij Jan. 9, 2015, 10:12 a.m. UTC | #1
On Fri, Nov 28, 2014 at 12:46 AM, Ray Jui <rjui@broadcom.com> wrote:

> Device tree binding documentation for Broadcom Cygnus pinctrl driver
>
> Signed-off-by: Ray Jui <rjui@broadcom.com>
> Reviewed-by: Scott Branden <sbranden@broadcom.com>
> ---
>  .../bindings/pinctrl/brcm,cygnus-pinctrl.txt       |   92 ++++++++++++++++++++
>  1 file changed, 92 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
>
> diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
> new file mode 100644
> index 0000000..86e4579
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
> @@ -0,0 +1,92 @@
> +Broadcom Cygnus Pin Controller
> +
> +The Cygnus pin controller supports setting the alternate functions of groups
> +of pins. Pinmux configuration on individual pins is not supported by the
> +Cygnus A0 SoC.
> +
> +Required properties:
> +
> +- compatible:
> +    Must be "brcm,cygnus-pinctrl"
> +
> +- reg:
> +    Define the base and range of the I/O address space that contain the Cygnus
> +pin control registers

The following is subnodes. Indicate clearly in the binding that these are
*not* properties of the main node, but individual subnodes.

> +- brcm,groups:
> +    This can be strings of one or more group names. This defines the group(s)
> +that one wants to configure
> +
> +- brcm,function:
> +    This is the alternate function that one wants to configure to. Valid
> +alternate functions are "alt1", "alt2", "alt3", "alt4"

NAK. We have standardized bindings for groups and functions,
and there are pending patches from Sören Brinkmann adding
this to the pinctrl DT parsing core.

Just use "groups" and "function" and refer to
Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt

Then "alt1", "alt2" etc are non-functional names of functions.
Use the real function names, like "spi0" or so. This
alt-business seems to be just a shortcut to make it
simple, don't do that.

Then you use e.g. "spi0" as a group name. I prefer you
call that "spi0_grp" or something to say it is a group of
pins associated with spi0, as spi0 is actually the
function.

If unsure of the definitions of group and function, refer
to Documentation/pinctrl.txt

Yours,
Linus Walleij
Ray Jui Jan. 9, 2015, 6:26 p.m. UTC | #2
On 1/9/2015 2:12 AM, Linus Walleij wrote:
> On Fri, Nov 28, 2014 at 12:46 AM, Ray Jui <rjui@broadcom.com> wrote:
> 
>> Device tree binding documentation for Broadcom Cygnus pinctrl driver
>>
>> Signed-off-by: Ray Jui <rjui@broadcom.com>
>> Reviewed-by: Scott Branden <sbranden@broadcom.com>
>> ---
>>  .../bindings/pinctrl/brcm,cygnus-pinctrl.txt       |   92 ++++++++++++++++++++
>>  1 file changed, 92 insertions(+)
>>  create mode 100644 Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
>>
>> diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
>> new file mode 100644
>> index 0000000..86e4579
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
>> @@ -0,0 +1,92 @@
>> +Broadcom Cygnus Pin Controller
>> +
>> +The Cygnus pin controller supports setting the alternate functions of groups
>> +of pins. Pinmux configuration on individual pins is not supported by the
>> +Cygnus A0 SoC.
>> +
>> +Required properties:
>> +
>> +- compatible:
>> +    Must be "brcm,cygnus-pinctrl"
>> +
>> +- reg:
>> +    Define the base and range of the I/O address space that contain the Cygnus
>> +pin control registers
> 
> The following is subnodes. Indicate clearly in the binding that these are
> *not* properties of the main node, but individual subnodes.
> 
Right. I'll fix the document.

>> +- brcm,groups:
>> +    This can be strings of one or more group names. This defines the group(s)
>> +that one wants to configure
>> +
>> +- brcm,function:
>> +    This is the alternate function that one wants to configure to. Valid
>> +alternate functions are "alt1", "alt2", "alt3", "alt4"
> 
> NAK. We have standardized bindings for groups and functions,
> and there are pending patches from Sören Brinkmann adding
> this to the pinctrl DT parsing core.
> 
> Just use "groups" and "function" and refer to
> Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
> 
> Then "alt1", "alt2" etc are non-functional names of functions.
> Use the real function names, like "spi0" or so. This
> alt-business seems to be just a shortcut to make it
> simple, don't do that.
> 
> Then you use e.g. "spi0" as a group name. I prefer you
> call that "spi0_grp" or something to say it is a group of
> pins associated with spi0, as spi0 is actually the
> function.
> 
Hmmm, I did this by following brcm,bcm11351-pinctrl.txt:
- function: String. Specifies the pin mux selection. Values must be one
of: "alt1", "alt2", "alt3", "alt4"

But you are right, in the pinctrl binding document it describes the
generic pin multiplexing nodes use "function" and "group".

Let me try to explain how the Cygnus pinctrl controller works and maybe
you can help to comment whether or not it's suitable for what's
described in pinctrl-binding.txt for the usage of "function" and "group".

The Cygnus pinctrl contoller has a limitation that the mux configuration
can only be group based. "group" here is a real configuration in the
Cygnus pinctrl controller registers. One can configure a "group" to
alternate function 1, 2, 3, or 4.

For example, the group "lcd" covers 30 pins. When I configure "lcd" to
alternate function 1, all 30 pins are muxed to LCD function. When
configured to function 2, all pins are muxed to SRAM function. Now, here
comes the issue, when configured to function 3, pins 1-15 and 20-30
become GPIO function, but pins 16-19 becomes SPI5 function. When it's
configured to function 4, all 30 pins become GPIO.

In some other cases, when I configure a group to other functions, there
could be spare pins which become unused (not brought out to the pad).
Or, the spare pins may also become a separate function.

Based on the LCD example, I'd assume I would do the following for the
default LCD function:

lcd_node {
	group = "lcd_grp";
	function = "lcd";
};

And in the case of function 3, I would call the function "spi5" and
assume the rest of pins become either GPIO (or unused)?

spi5_node {
	group = "lcd_grp";
	function = "spi5";
};


> If unsure of the definitions of group and function, refer
> to Documentation/pinctrl.txt
> 
> Yours,
> Linus Walleij
>
Linus Walleij Jan. 13, 2015, 8:20 a.m. UTC | #3
On Fri, Jan 9, 2015 at 7:26 PM, Ray Jui <rjui@broadcom.com> wrote:
> On 1/9/2015 2:12 AM, Linus Walleij wrote:

>> Just use "groups" and "function" and refer to
>> Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
>>
>> Then "alt1", "alt2" etc are non-functional names of functions.
>> Use the real function names, like "spi0" or so. This
>> alt-business seems to be just a shortcut to make it
>> simple, don't do that.
>>
>> Then you use e.g. "spi0" as a group name. I prefer you
>> call that "spi0_grp" or something to say it is a group of
>> pins associated with spi0, as spi0 is actually the
>> function.
>>
> Hmmm, I did this by following brcm,bcm11351-pinctrl.txt:
> - function: String. Specifies the pin mux selection. Values must be one
> of: "alt1", "alt2", "alt3", "alt4"
>
> But you are right, in the pinctrl binding document it describes the
> generic pin multiplexing nodes use "function" and "group".

Note "function" and "groups". Note groups is pluralis. You can
select multiple groups for a single function.

> For example, the group "lcd" covers 30 pins. When I configure "lcd" to
> alternate function 1, all 30 pins are muxed to LCD function. When
> configured to function 2, all pins are muxed to SRAM function. Now, here
> comes the issue, when configured to function 3, pins 1-15 and 20-30
> become GPIO function, but pins 16-19 becomes SPI5 function. When it's
> configured to function 4, all 30 pins become GPIO.

I would split the use case in two groups for LCD and SRAM,
and three groups for GPIO:
"lcd_grp", "sram_grp", "gpio-1-15_grp",
"gpio-16-19_grp", "gpio-20-30_grp", "spi5_grp"

Valid combinations become

function = "lcd"
groups = "lcd_grp";

function = "sram"
groups = "sram_grp"

For all GPIO only this:

function = "gpio"
groups = "gpio-1-16_grp", "gpio-16-19_grp", "gpio-20-30_grp"

For a combined GPIO+SPI:

function = "gpio"
groups = "gpio-1-16_grp", "gpio-20-30_grp"

function = "spi5"
groups = "spi5_grp"

The pinctrl runtile will protest if you try to combine spi5_grp
with gpio-16-19_grp.

> In some other cases, when I configure a group to other functions, there
> could be spare pins which become unused (not brought out to the pad).
> Or, the spare pins may also become a separate function.

That's cool.

> Based on the LCD example, I'd assume I would do the following for the
> default LCD function:
>
> lcd_node {
>         group = "lcd_grp";
>         function = "lcd";
> };
>
> And in the case of function 3, I would call the function "spi5" and
> assume the rest of pins become either GPIO (or unused)?
>
> spi5_node {
>         group = "lcd_grp";
>         function = "spi5";
> };

Looks cool per above.

You need some clever code in the driver to handle double-configuration
of registers and so on, but I think it can be done.

Using pin control as a GPIO backend can be a bit tricky and will need
some testing and elaboration, but the subsystem will block collisions.

Yours,
Linus Walleij
Ray Jui Jan. 13, 2015, 5:14 p.m. UTC | #4
On 1/13/2015 12:20 AM, Linus Walleij wrote:
> On Fri, Jan 9, 2015 at 7:26 PM, Ray Jui <rjui@broadcom.com> wrote:
>> On 1/9/2015 2:12 AM, Linus Walleij wrote:
> 
>>> Just use "groups" and "function" and refer to
>>> Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
>>>
>>> Then "alt1", "alt2" etc are non-functional names of functions.
>>> Use the real function names, like "spi0" or so. This
>>> alt-business seems to be just a shortcut to make it
>>> simple, don't do that.
>>>
>>> Then you use e.g. "spi0" as a group name. I prefer you
>>> call that "spi0_grp" or something to say it is a group of
>>> pins associated with spi0, as spi0 is actually the
>>> function.
>>>
>> Hmmm, I did this by following brcm,bcm11351-pinctrl.txt:
>> - function: String. Specifies the pin mux selection. Values must be one
>> of: "alt1", "alt2", "alt3", "alt4"
>>
>> But you are right, in the pinctrl binding document it describes the
>> generic pin multiplexing nodes use "function" and "group".
> 
> Note "function" and "groups". Note groups is pluralis. You can
> select multiple groups for a single function.
> 
>> For example, the group "lcd" covers 30 pins. When I configure "lcd" to
>> alternate function 1, all 30 pins are muxed to LCD function. When
>> configured to function 2, all pins are muxed to SRAM function. Now, here
>> comes the issue, when configured to function 3, pins 1-15 and 20-30
>> become GPIO function, but pins 16-19 becomes SPI5 function. When it's
>> configured to function 4, all 30 pins become GPIO.
> 
> I would split the use case in two groups for LCD and SRAM,
> and three groups for GPIO:
> "lcd_grp", "sram_grp", "gpio-1-15_grp",
> "gpio-16-19_grp", "gpio-20-30_grp", "spi5_grp"
> 

> Valid combinations become
> 
> function = "lcd"
> groups = "lcd_grp";
> 
> function = "sram"
> groups = "sram_grp"
> 
> For all GPIO only this:
> 
> function = "gpio"
> groups = "gpio-1-16_grp", "gpio-16-19_grp", "gpio-20-30_grp"
> 
> For a combined GPIO+SPI:
> 
> function = "gpio"
> groups = "gpio-1-16_grp", "gpio-20-30_grp"
> 
> function = "spi5"
> groups = "spi5_grp"
> 
> The pinctrl runtile will protest if you try to combine spi5_grp
> with gpio-16-19_grp.
> 
Okay this makes sense. Thanks.

>> In some other cases, when I configure a group to other functions, there
>> could be spare pins which become unused (not brought out to the pad).
>> Or, the spare pins may also become a separate function.
> 
> That's cool.
> 
>> Based on the LCD example, I'd assume I would do the following for the
>> default LCD function:
>>
>> lcd_node {
>>         group = "lcd_grp";
>>         function = "lcd";
>> };
>>
>> And in the case of function 3, I would call the function "spi5" and
>> assume the rest of pins become either GPIO (or unused)?
>>
>> spi5_node {
>>         group = "lcd_grp";
>>         function = "spi5";
>> };
> 
> Looks cool per above.
> 
> You need some clever code in the driver to handle double-configuration
> of registers and so on, but I think it can be done.
Let me see what I can come up with.

> 
> Using pin control as a GPIO backend can be a bit tricky and will need
> some testing and elaboration, but the subsystem will block collisions.
> 
> Yours,
> Linus Walleij
>
Ray Jui Jan. 23, 2015, 2:14 a.m. UTC | #5
On 1/13/2015 12:20 AM, Linus Walleij wrote:
> On Fri, Jan 9, 2015 at 7:26 PM, Ray Jui <rjui@broadcom.com> wrote:
>> On 1/9/2015 2:12 AM, Linus Walleij wrote:
> 
>>> Just use "groups" and "function" and refer to
>>> Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
>>>
>>> Then "alt1", "alt2" etc are non-functional names of functions.
>>> Use the real function names, like "spi0" or so. This
>>> alt-business seems to be just a shortcut to make it
>>> simple, don't do that.
>>>
>>> Then you use e.g. "spi0" as a group name. I prefer you
>>> call that "spi0_grp" or something to say it is a group of
>>> pins associated with spi0, as spi0 is actually the
>>> function.
>>>
>> Hmmm, I did this by following brcm,bcm11351-pinctrl.txt:
>> - function: String. Specifies the pin mux selection. Values must be one
>> of: "alt1", "alt2", "alt3", "alt4"
>>
>> But you are right, in the pinctrl binding document it describes the
>> generic pin multiplexing nodes use "function" and "group".
> 
> Note "function" and "groups". Note groups is pluralis. You can
> select multiple groups for a single function.
> 
>> For example, the group "lcd" covers 30 pins. When I configure "lcd" to
>> alternate function 1, all 30 pins are muxed to LCD function. When
>> configured to function 2, all pins are muxed to SRAM function. Now, here
>> comes the issue, when configured to function 3, pins 1-15 and 20-30
>> become GPIO function, but pins 16-19 becomes SPI5 function. When it's
>> configured to function 4, all 30 pins become GPIO.
> 
> I would split the use case in two groups for LCD and SRAM,
> and three groups for GPIO:
> "lcd_grp", "sram_grp", "gpio-1-15_grp",
> "gpio-16-19_grp", "gpio-20-30_grp", "spi5_grp"
> 
> Valid combinations become
> 
> function = "lcd"
> groups = "lcd_grp";
> 
> function = "sram"
> groups = "sram_grp"
> 
> For all GPIO only this:
> 
> function = "gpio"
> groups = "gpio-1-16_grp", "gpio-16-19_grp", "gpio-20-30_grp"
> 
> For a combined GPIO+SPI:
> 
> function = "gpio"
> groups = "gpio-1-16_grp", "gpio-20-30_grp"
> 
> function = "spi5"
> groups = "spi5_grp"
> 
> The pinctrl runtile will protest if you try to combine spi5_grp
> with gpio-16-19_grp.
> 
>> In some other cases, when I configure a group to other functions, there
>> could be spare pins which become unused (not brought out to the pad).
>> Or, the spare pins may also become a separate function.
> 
> That's cool.
> 
>> Based on the LCD example, I'd assume I would do the following for the
>> default LCD function:
>>
>> lcd_node {
>>         group = "lcd_grp";
>>         function = "lcd";
>> };
>>
>> And in the case of function 3, I would call the function "spi5" and
>> assume the rest of pins become either GPIO (or unused)?
>>
>> spi5_node {
>>         group = "lcd_grp";
>>         function = "spi5";
>> };
> 
> Looks cool per above.
> 
> You need some clever code in the driver to handle double-configuration
> of registers and so on, but I think it can be done.
> 
> Using pin control as a GPIO backend can be a bit tricky and will need
> some testing and elaboration, but the subsystem will block collisions.
> 
> Yours,
> Linus Walleij
> 

Hi Linus,

I have another question here. In the B0 revision of our Cygnus chip, the
ASIC team added a feature to allow individual pins to be muxed to GPIO.
The pinmux controller can still only do group-based muxing in general,
but at the same time, you can override most (but not all) individual
pins to GPIO.

I believe this HW design actually forces us to mix use "groups" and
"pins" in DT.

For example, assuming we mux pins 1 - 10 as MMC (one cmd line, one clk
line, and 8 data lines). One might make the decision that he only needs
4 data lines instead of 8 data lines, and he wants to free up the 4 data
lines and uses as GPIO. Based on this example, is the following DT
configuration valid?

sd_node {
    function = "sd";
    groups = "sd_grps";
};

gpio_node {
    function = "gpio";
    pins = "gpio_7", "gpio_8", "gpio_9", "gpio_10"; /* assuming 1:1
mapping between gpio and pin number to make this example simple */
};

Thanks,

Ray
Ray Jui Jan. 23, 2015, 6:49 a.m. UTC | #6
On 1/22/2015 6:14 PM, Ray Jui wrote:
> 
> 
> On 1/13/2015 12:20 AM, Linus Walleij wrote:
>> On Fri, Jan 9, 2015 at 7:26 PM, Ray Jui <rjui@broadcom.com> wrote:
>>> On 1/9/2015 2:12 AM, Linus Walleij wrote:
>>
>>>> Just use "groups" and "function" and refer to
>>>> Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
>>>>
>>>> Then "alt1", "alt2" etc are non-functional names of functions.
>>>> Use the real function names, like "spi0" or so. This
>>>> alt-business seems to be just a shortcut to make it
>>>> simple, don't do that.
>>>>
>>>> Then you use e.g. "spi0" as a group name. I prefer you
>>>> call that "spi0_grp" or something to say it is a group of
>>>> pins associated with spi0, as spi0 is actually the
>>>> function.
>>>>
>>> Hmmm, I did this by following brcm,bcm11351-pinctrl.txt:
>>> - function: String. Specifies the pin mux selection. Values must be one
>>> of: "alt1", "alt2", "alt3", "alt4"
>>>
>>> But you are right, in the pinctrl binding document it describes the
>>> generic pin multiplexing nodes use "function" and "group".
>>
>> Note "function" and "groups". Note groups is pluralis. You can
>> select multiple groups for a single function.
>>
>>> For example, the group "lcd" covers 30 pins. When I configure "lcd" to
>>> alternate function 1, all 30 pins are muxed to LCD function. When
>>> configured to function 2, all pins are muxed to SRAM function. Now, here
>>> comes the issue, when configured to function 3, pins 1-15 and 20-30
>>> become GPIO function, but pins 16-19 becomes SPI5 function. When it's
>>> configured to function 4, all 30 pins become GPIO.
>>
>> I would split the use case in two groups for LCD and SRAM,
>> and three groups for GPIO:
>> "lcd_grp", "sram_grp", "gpio-1-15_grp",
>> "gpio-16-19_grp", "gpio-20-30_grp", "spi5_grp"
>>
>> Valid combinations become
>>
>> function = "lcd"
>> groups = "lcd_grp";
>>
>> function = "sram"
>> groups = "sram_grp"
>>
>> For all GPIO only this:
>>
>> function = "gpio"
>> groups = "gpio-1-16_grp", "gpio-16-19_grp", "gpio-20-30_grp"
>>
>> For a combined GPIO+SPI:
>>
>> function = "gpio"
>> groups = "gpio-1-16_grp", "gpio-20-30_grp"
>>
>> function = "spi5"
>> groups = "spi5_grp"
>>
>> The pinctrl runtile will protest if you try to combine spi5_grp
>> with gpio-16-19_grp.
>>
>>> In some other cases, when I configure a group to other functions, there
>>> could be spare pins which become unused (not brought out to the pad).
>>> Or, the spare pins may also become a separate function.
>>
>> That's cool.
>>
>>> Based on the LCD example, I'd assume I would do the following for the
>>> default LCD function:
>>>
>>> lcd_node {
>>>         group = "lcd_grp";
>>>         function = "lcd";
>>> };
>>>
>>> And in the case of function 3, I would call the function "spi5" and
>>> assume the rest of pins become either GPIO (or unused)?
>>>
>>> spi5_node {
>>>         group = "lcd_grp";
>>>         function = "spi5";
>>> };
>>
>> Looks cool per above.
>>
>> You need some clever code in the driver to handle double-configuration
>> of registers and so on, but I think it can be done.
>>
>> Using pin control as a GPIO backend can be a bit tricky and will need
>> some testing and elaboration, but the subsystem will block collisions.
>>
>> Yours,
>> Linus Walleij
>>
> 
> Hi Linus,
> 
> I have another question here. In the B0 revision of our Cygnus chip, the
> ASIC team added a feature to allow individual pins to be muxed to GPIO.
> The pinmux controller can still only do group-based muxing in general,
> but at the same time, you can override most (but not all) individual
> pins to GPIO.
> 
> I believe this HW design actually forces us to mix use "groups" and
> "pins" in DT.
> 
> For example, assuming we mux pins 1 - 10 as MMC (one cmd line, one clk
> line, and 8 data lines). One might make the decision that he only needs
> 4 data lines instead of 8 data lines, and he wants to free up the 4 data
> lines and uses as GPIO. Based on this example, is the following DT
> configuration valid?
> 
> sd_node {
>     function = "sd";
>     groups = "sd_grps";
> };
> 
> gpio_node {
>     function = "gpio";
>     pins = "gpio_7", "gpio_8", "gpio_9", "gpio_10"; /* assuming 1:1
> mapping between gpio and pin number to make this example simple */
> };
> 
> Thanks,
> 
> Ray
>

I dig into the pinctrl framework code a bit more and found that I can
use pinctrl_request_gpio from the GPIO driver and implement
gpio_request_enable in the pinctrl driver.

The only problem I see now is that these APIs seem to expect the use of
global GPIO numbers? And all pinctrl drivers I checked seem to be hard
coding the GPIO to pin mapping when declaring the struct
pinctrl_gpio_range array. How would this work in a system like ours that
have 3 GPIO controllers and was required to use a dynamic GPIO number
(i.e., we use gpio->base = -1, so it derives the base from
CONFIG_ARCH_NR_GPIO and goes backwards)?

I guess I can do some runtime calculation in my pinctrl driver to figure
out the GPIO->pin mapping based on CONFIG_ARCH_NR_GPIO, but this is
assuming that we always fix the order of the device nodes of the 3 GPIO
controllers.

I hope I'm not missing something here?

Thanks,

Ray
Linus Walleij Jan. 30, 2015, 1:54 p.m. UTC | #7
On Fri, Jan 23, 2015 at 3:14 AM, Ray Jui <rjui@broadcom.com> wrote:

> I have another question here. In the B0 revision of our Cygnus chip, the
> ASIC team added a feature to allow individual pins to be muxed to GPIO.
> The pinmux controller can still only do group-based muxing in general,
> but at the same time, you can override most (but not all) individual
> pins to GPIO.
>
> I believe this HW design actually forces us to mix use "groups" and
> "pins" in DT.
>
> For example, assuming we mux pins 1 - 10 as MMC (one cmd line, one clk
> line, and 8 data lines). One might make the decision that he only needs
> 4 data lines instead of 8 data lines, and he wants to free up the 4 data
> lines and uses as GPIO.

I would split the 8 available data lines in two groups,
like "data-1-4" and "data-5-8" since the use case is such
that either you use four or eight lines, not 6 or 7, either
just "data-1-4" or both "data-1-4" and "data-5-8".

> Based on this example, is the following DT
> configuration valid?

> sd_node {
>     function = "sd";
>     groups = "sd_grps";
> };
>
> gpio_node {
>     function = "gpio";
>     pins = "gpio_7", "gpio_8", "gpio_9", "gpio_10"; /* assuming 1:1
> mapping between gpio and pin number to make this example simple */
> };

Muxing an individual GPIO from the device tree is seldom a
good idea as you realized in your follow-up mail ;)

But this:

sd_node {
     function = "sd";
     groups = "data-1-4", "data-5-8", "other-pin-group";
};

Is perfectly fine. One function, several groups.

Yours,
Linus Walleij
Linus Walleij Jan. 30, 2015, 2:18 p.m. UTC | #8
On Fri, Jan 23, 2015 at 7:49 AM, Ray Jui <rjui@broadcom.com> wrote:

> I dig into the pinctrl framework code a bit more and found that I can
> use pinctrl_request_gpio from the GPIO driver and implement
> gpio_request_enable in the pinctrl driver.

Yep :) ain't it nice.

> The only problem I see now is that these APIs seem to expect the use of
> global GPIO numbers?

No they don't, only if you use the deprecated pinctrl_add_gpio_range().

Instead, when you register your struct gpio_chip, use
gpiochip_add_pin_range() and this will use relative offsets
without relying on global GPIO numbers.

This latter call replaces pinctrl_add_gpio_range().

> I hope I'm not missing something here?

You're missing gpiochip_add_pin_range() ;)

Yours,
Linus Walleij
Ray Jui Jan. 30, 2015, 5:01 p.m. UTC | #9
On 1/30/2015 6:18 AM, Linus Walleij wrote:
> On Fri, Jan 23, 2015 at 7:49 AM, Ray Jui <rjui@broadcom.com> wrote:
> 
>> I dig into the pinctrl framework code a bit more and found that I can
>> use pinctrl_request_gpio from the GPIO driver and implement
>> gpio_request_enable in the pinctrl driver.
> 
> Yep :) ain't it nice.
> 
>> The only problem I see now is that these APIs seem to expect the use of
>> global GPIO numbers?
> 
> No they don't, only if you use the deprecated pinctrl_add_gpio_range().
> 
> Instead, when you register your struct gpio_chip, use
> gpiochip_add_pin_range() and this will use relative offsets
> without relying on global GPIO numbers.
> 
> This latter call replaces pinctrl_add_gpio_range().
> 
>> I hope I'm not missing something here?
> 
> You're missing gpiochip_add_pin_range() ;)
> 
> Yours,
> Linus Walleij
> 
Yeah, I realized this while implementing the driver, :)

I'm now in the final testing/cleaning phase of both Cygnus pinmux and
gpio/pinconf driver. I really appreciate that the pinctrl framework
allows the two to work seamlessly with each other and at the same time
provides the necessary interface to bridge the two, :)

I should be able to send out the patches of the two drivers for review
sometime next week.

Thanks for the help!

Ray
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
new file mode 100644
index 0000000..86e4579
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/brcm,cygnus-pinctrl.txt
@@ -0,0 +1,92 @@ 
+Broadcom Cygnus Pin Controller
+
+The Cygnus pin controller supports setting the alternate functions of groups
+of pins. Pinmux configuration on individual pins is not supported by the
+Cygnus A0 SoC.
+
+Required properties:
+
+- compatible:
+    Must be "brcm,cygnus-pinctrl"
+
+- reg:
+    Define the base and range of the I/O address space that contain the Cygnus
+pin control registers
+
+- brcm,groups:
+    This can be strings of one or more group names. This defines the group(s)
+that one wants to configure
+
+- brcm,function:
+    This is the alternate function that one wants to configure to. Valid
+alternate functions are "alt1", "alt2", "alt3", "alt4"
+
+Each child node represents a configuration. Client devices reference the the
+child node to enable the mux configuration.
+
+For example:
+
+	pinctrl: pinctrl@0x0301d0c8 {
+		compatible = "brcm,cygnus-pinctrl";
+		reg = <0x0301d0c8 0x2c>;
+
+		i2s_0: i2s_0 {
+			brcm,groups = "smart_card0", "smart_card0_fcb";
+			brcm,function = "alt2";
+		};
+
+		i2s_1: i2s_1 {
+			brcm,groups = "smart_card1", "smart_card1_fcb";
+			brcm,function = "alt2";
+		};
+
+		spi_0: spi_0 {
+			brcm,groups = "spi0";
+			brcm,function = "alt1";
+		};
+	}
+
+	spi0@18028000 {
+			compatible = "arm,pl022", "arm,primecell";
+			reg = <0x18028000 0x1000>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+			pinctrl-0 = <&spi_0>;
+			clocks = <&axi81_clk>;
+			clock-names = "apb_pclk";
+	};
+
+Consider the following snapshot of Cygnus pinmux table:
+
+number    pin            group              alt1             alt2        alt3        alt4
+------    ---            ----               ----             ----        ----        ----
+42        sc0_clk        smart_card0        SMART CARD0      I2S_0       N/A         chip_gpio24
+43        sc0_cmdvcc_l   smart_card0        SMART CARD0      I2S_0       N/A         STRAP
+44        sc0_detect     smart_card0        SMART CARD0      I2S_0       N/A         chip_gpio25
+45        sc0_fcb        smart_card0_fcb    SMART CARD0_FCB  I2S_0       N/A         chip_gpio26
+46        sc0_io         smart_card0        SMART CARD0      I2S_0       N/A         chip_gpio27
+47        sc0_rst_l      smart_card0        SMART CARD0      SPDIF       N/A         STRAP
+
+Note due to limitation of the Cygnus hardware, pinmux configuration can only
+be group based. To enable I2S_0 function, one needs the following child node
+configuration:
+
+	i2s_0: i2s_0 {
+		brcm,groups = "smart_card0", "smart_card0_fcb";
+		brcm,function = "alt2";
+	};
+
+This tells the Cygnus pin controller to configure groups "smart_card0" and
+"smart_card0_fcb" to I2S_0. With this configuration, pins 42, 43, 44, 45, 46
+become I2C_0, and pin 47 becomes SPDIF
+
+Consider another example, that one wants to configure the above pins as GPIO:
+
+	gpio_24_27: gpio_24_27 {
+		brcm,groups = "smart_card0", "smart_card0_fcb";
+		brcm,function = "alt4";
+	};
+
+With the above configuration, pins 42, 44, 45, 46 become GPIO, and 43 and 47
+become reserved for STRAP