Skip to content

Conversation

@MulinChao
Copy link
Contributor

@MulinChao MulinChao commented Mar 10, 2022

This pull request contains the following changes:

  • Provide NPCX pinctrl implementation based on Road from pinmux to pinctrl #39740.
    Add pinctrl implementation in pinctrl_npcx.c.
    Merge npcx pinctrl configuration into pinctrl_soc_pin_t structure in soc/arm/nuvoton_npcx/common/pinctrl_soc.h
    Keep part of the existing but non-generic NPCX soc pinctrl utilities still. (Will remove them in the following PRs.)
  • Implement pinctrl mechanism for npcx peripheral drivers such as uart, pwm, espi and so on.
    Inherit pinctrl-device in peripheral drivers' yaml files
    Add required 'pinctrl-names' properties on related peripheral device-tree nodes.
    Replace npcx utilities with pinctrl APIs for generic pinctrl functionalities in the driver.

Verified devices: (ongoing,)
npcx7m6fb_evb, npcx9m6f_evb, and volteer/lazer chromebooks.

Since Nuvton ec has been applied on notebooks for decades, the needs such as firmware backward compatibility are to be considered. Hence, there are three consideration factors during pinctrl driver refactoring.

  1. The pinctrl functionalities are scatted in different modules such as scfg, glue, gpio, and peripheral devices themselves. Not all IO pads have all pinctrl properties from the cost perspective.
  2. The IO-pads' functionalities such as open-drain, pull-up/down are different from gpio and peripheral devices in npcx series. For example, users can select pull-up/down, push-pull and open-drain properties of gpiob5/b4 via gpio module. But it will be open-drain bias type automatically if pin-mux is selected to the i2c module. The settings of gpiob5/b4 don't influence i2c's pad functionalities even though they share the same pins. (Besides low-voltage input feature. It influences both gpio and peripheral devices.)
  3. The layout for corresponding peripheral/io and control reg/bit is irregular. The mapping tables for pin-muxing, 1.8v support, and so on are introduced and needed in the current implementation. But it is not one-on-one mapping between all pinctrl functionalities. For example, users only need to set one control bit to switch 8 pins from gpio to espi module, but they need to configure these pins one by one if they are selected to gpio. And few pins need two or more control bits for pin-muxing if they share two or more peripheral devices.

This PR is the first attempt for npcx pinctrl driver and adds pinctrl nodes for each npcx series. According to the above points, it introduces pinctrl nodes for peripheral devices. And wraps all configurations no matter general pin-muxing or soc-specific features such as pinmux-locked in pinctrl_soc.h. Users set pin configuration via these nodes in the board layout DT file by the following ways:

  1. Pinmuxing for peripheral devices
&uart1 {
        status = "okay";
        pinctrl-0 = <&pad_uart1_2_sin_sout>; /* Use UART1_SL2 ie. PIN64.65 */
        pinctrl-names = "default";
};
  1. Configure peripheral devices' pad property by overwriting prebuild nodes in pinctrl nodes directly. (Not all of them are fully configurable.)
&pad_i2c0_0_sda_scl {
	bias-pull-up; /* Enable internal pull-up for i2c0_0 */
	pinmux-locked; /* Lock pinmuxing */
};

&i2c0_0 {
	status = "okay";
	pinctrl-0 = <&pad_i2c0_0_sda_scl>;
	pinctrl-names = "default";
	clock-frequency = <I2C_BITRATE_FAST>;
};

Regarding gpio and psl pads configurations via pinctrl driver, they will be introduced in the following PR.

@github-actions github-actions bot added area: ADC Analog-to-Digital Converter (ADC) area: Boards area: Devicetree area: Devicetree Binding PR modifies or adds a Device Tree binding area: I2C area: PWM Pulse Width Modulation labels Mar 10, 2022
@MulinChao MulinChao marked this pull request as ready for review March 15, 2022 05:28
@MulinChao
Copy link
Contributor Author

Hi all, this PR has been verified on all devices on my side and marked as ready. Any comments are highly appreciated.

@MulinChao MulinChao force-pushed the npcx_pinctrl branch 2 times, most recently from 9b02862 to 37a003d Compare March 15, 2022 06:15
@carlescufi carlescufi mentioned this pull request Mar 15, 2022
29 tasks
@keith-zephyr
Copy link
Contributor

keith-zephyr commented Mar 16, 2022

Some general comments:

Does this pinctrl driver provide any mechanism for setting the pullup/pulldown, and open drain properties? I believe these are set using the GPIO module in the NPCX, while the alternate function support is set through the system configuration DEVALTn registers.

It might be useful to add an NPCX specific pinctrl state called "locked". This state would be used set the corresponding DEVALTn_LK register.

Right now, as gerard notes, you have setup the default pinctrl for each driver. The I2C ports support is currently modeled as an I2C port/I2C controller pair. With the pinctrl support, this could be refactored so that the board uses the pinctrl-0 property to select the correct I2C port.

For example, boards using I2C controller 4, port 1, are configured with the current implementation like this:

&i2c6_1 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>;
};

This could be refactored as:

/* Use I2C 6, port 0 */
&i2c6 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>;
	pinctrl-0 = <&alt2_i2c6_0_sl>; /* PINC2.C1 */
};
/* Use I2C 6, port 1 */
&i2c6 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>;
	pinctrl-0 = <&alt6_i2c6_1_sl>; /* PINE4.E3 */
};

@MulinChao MulinChao requested a review from carlescufi March 17, 2022 06:17
@MulinChao
Copy link
Contributor Author

MulinChao commented Mar 17, 2022

Thanks for your comments. Please see my reply below.

Some general comments:
Does this pinctrl driver provide any mechanism for setting the pullup/pulldown, and open drain properties? I believe these are set using the GPIO module in the NPCX, while the alternate function support is set through the system configuration DEVALTn registers.

Not only NPCX, the other soc series also use gpios property to configure the pullup/pulldown, and open drain functionalities of IO pads. For alternative functions, they are usually configured by pinctrl-0/1/2 of the peripheral device DT node.

It might be useful to add an NPCX specific pinctrl state called "locked". This state would be used set the corresponding DEVALTn_LK register.

Indeed, it is a good idea. I will add a new pinctrl state, locked, and its mechanism in this PR. Then, will submit it for code review after passing verification on my side.

Right now, as gerard notes, you have setup the default pinctrl for each driver. The I2C ports support is currently modeled as an I2C port/I2C controller pair. With the pinctrl support, this could be refactored so that the board uses the pinctrl-0 property to select the correct I2C port.

Here is the chart which demonstrates npcx I2C port and controller pair.

              DEVALTn   Port SEL
                 |        |
                 |      |\|
 SCL/SDA Port0 x-+------| \     +--------------+
                        |  |----|   SMB/I2C    |
                        |  |----| Controller N |
 SCL/SDA Port1 x-+------|  |    +--------------+
                 |      | /
                 |      |/
              DEVALTn

If users use both i2c6_0 and i2c6_1 ports for the application, all relevant selection bits in DEVALTn must be set, and switch pin-mux from GPIO to I2C. By setting the i2c-port DT node's status to okay. Or users need to set pinctrl-0 explicitly as below:

/* Use I2C 6, port 0  only */
&i2c6 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>;
	pinctrl-0 = <&alt2_i2c6_0_sl>; /* PINC2.C1 */
};

/* Use I2C 6, port 1 only */
&i2c6 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>;
	pinctrl-0 = <&alt6_i2c6_1_sl>; /* PINE4.E3 */
};

/* Use I2C 6, port 0 and 1 */
&i2c6 {
	status = "okay";
	clock-frequency = <I2C_BITRATE_FAST>;
	pinctrl-0 = <&alt2_i2c6_0_sl &alt6_i2c6_1_sl>; /* PINC2.C1 PINE4.E3 */
};

In my opinion, I still think putting pinctrl-0 in i2c-port is more suitable since it fits our design and prevents users set wrong configurations in this property.

@keith-zephyr
Copy link
Contributor

In my opinion, I still think putting pinctrl-0 in i2c-port is more suitable since it fits our design and prevents users set wrong configurations in this property.

This was my thought as well. This will also simplify the devicetree for the user. Today the user needs to enable both the I2C port (&i2c0_0) and the I2C controller (&i2c_ctrl0).

@MulinChao MulinChao force-pushed the npcx_pinctrl branch 3 times, most recently from 8cfaae0 to f3d43ac Compare May 9, 2022 06:52
Copy link
Member

@gmarull gmarull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm, a couple of minor issues

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this property should be part of the pwm6_gpc0 node

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Setting bit 7 in PWMCTLEX selects the type of the PWM_n output buffer to push-pull or open-drain. I don't know it's a good idea to move it to pinctrl_npcx.c. Hence, I still keep it in the pwm driver.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review the latest PR.

Comment on lines 224 to 225
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs to be handled by a pin control driver, not like this. If some pin properties are handled directly by certain IP blocks (like e.g. Nordic), you can either encode address/bit in the state node or make use of the PINCTRL_STORE_REG, so that you also get the peripheral address when being called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Will modify it for code review later.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. The latest PR has moved sources that configure drive-open-drain from pwm_npcx.c to pinctrl_npcx.c. In order to make sure static casting of reg is reliable, a new property, drive-supported, is introduced in pwm pinctrl rebuild nodes.

gmarull
gmarull previously approved these changes May 10, 2022
Copy link
Member

@gmarull gmarull left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the continued effort

@MulinChao
Copy link
Contributor Author

Thanks for the continued effort

Thanks for the detailed explanation. It helps a lot.

Hi @keith-zephyr, do you have any comments for the latest version?

@keith-zephyr
Copy link
Contributor

Thanks for the continued effort

Thanks for the detailed explanation. It helps a lot.

Hi @keith-zephyr, do you have any comments for the latest version?

I have been on vacation. But I will review this tomorrow (May 11).

@MulinChao
Copy link
Contributor Author

In order to resolve the conflicts, I rebase the branch onto ToT. Sorry for dismissing @gmarull's approval. Could you review it again?

gmarull
gmarull previously approved these changes May 11, 2022
keith-zephyr
keith-zephyr previously approved these changes May 11, 2022
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking comment - this adds 4 bytes to every pinctrl node correct? But this is only needed by the PWM nodes.

If you can repack the bitfields of npcx_periph to use 3 bits to store the PWM instance number. You could then store the PWM base addresses into npcx_pinctrl_cfg similar to the base_scfg field.

Using PINCTRL_STORE_REG is a cleaner approach, so you would need to evaluate how much flash space is saved by encoding the PWM instance in place of using reg.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking comment - this adds 4 bytes to every pinctrl node correct? But this is only needed by the PWM nodes.

ML> If you mean each given device that applies pinctrl mechanism will increase 4 bytes, yes, you're correct.

If you can repack the bitfields of npcx_periph to use 3 bits to store the PWM instance number. You could then store the PWM base addresses into npcx_pinctrl_cfg similar to the base_scfg field.
Using PINCTRL_STORE_REG is a cleaner approach, so you would need to evaluate how much flash space is saved by encoding the PWM instance in place of using reg.

ML> I have thought about that before. But if we have a chance to add drive mode support for the other peripheral devices, PINCTRL_STORE_REG is a clearer way to maintain pinctrl mechanism. As I mentioned above, the flash space increases by 4 bytes for every device using pinctl-names and proctrl-0/1/2 properties for pinctrl mechanism. If we need to save flash spaces in the furture, I prefer to create the other PR that includes:

  1. Restore device's label name in npcx_periph
  2. Use device_get_binding to get the correct register address.

But the cost is the latency of selecting drive mode is longer.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that device_get_binding is rarely needed these days, DEVICE_DT_GET can be used for most situations. It is sometimes not necessary to store a device pointer either, see e.g. how GD32 pinctrl driver handles selected port.

MulinChao added 8 commits May 11, 2022 18:48
This CL is the initial version for npcx pinctrl driver and introduces
pinctrl nodes for both IO-pads and peripheral devices for each npcx
series. Users can set pin configuration via these nodes in the board
layout DT file. It also wraps all configurations related to pin-muxing
in pinctrl_soc.h. Regarding the other pin properties, we will implement
them later.

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in uart driver.

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in i2c driver.

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in pwm driver.

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in ps2 driver.

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in npcx tachometer driver.

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in npcx adc driver. Please notice users need to
configure the corresponding pinctrl nodes in 'pinctrl-0' property in the
adc0 DT node. For example, if ADC0 and ADC2 channels are selected for
the application, please add the follwoings in your board DT layout file.

&adc0 {
	status = "okay";
	/* Use adc0 channel 0 and 2 for 'adc_api' driver tests */
	pinctrl-0 = <&adc0_chan0_gp45
		     &adc0_chan2_gp43>;
	pinctrl-names = "default";
};

Signed-off-by: Mulin Chao <[email protected]>
Replace soc-specific pin functions with Zephyr pinctrl api functions for
pin-mux configuration in npcx eSPI and host_subs driver.

Signed-off-by: Mulin Chao <[email protected]>
@MulinChao MulinChao dismissed stale reviews from keith-zephyr and gmarull via 4c9fbb6 May 12, 2022 02:33
@MulinChao
Copy link
Contributor Author

Hi @gmarull & @keith-zephyr, sorry for the noise. The latest changes only rename variables for the recent comments. Please review it and give your comment freely.
BTW, I also submitted a new PR adding a helper macro to prevent build error if the target device hasn't reg property.

@MaureenHelm MaureenHelm merged commit 33c7119 into zephyrproject-rtos:main May 12, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ADC Analog-to-Digital Converter (ADC) area: Boards area: Devicetree Binding PR modifies or adds a Device Tree binding area: Devicetree area: I2C area: PWM Pulse Width Modulation platform: Nuvoton NPCX Nuvoton NPCX

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants