Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers/mfd: it8801: Implement ITE IT8801 mfd drivers #79416

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

GTLin08
Copy link
Collaborator

@GTLin08 GTLin08 commented Oct 4, 2024

This PR Implements the ITE IT8801 IO expander multi-function device driver. The IO expander provides GPIO, PWM, and keyboard functions via the I2C bus.

Copy link
Contributor

@keith-zephyr keith-zephyr left a comment

Choose a reason for hiding this comment

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

Also consider running clang-format on all the files.

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(mfd_ite_it8801, CONFIG_MFD_LOG_LEVEL);

static const struct device *kbd_dev = DEVICE_DT_GET_ANY(ite_it8801_kbd);
Copy link
Contributor

Choose a reason for hiding this comment

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

This driver supports multiple instances, but this this assumes that there is only one IT8801 defined.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed, use multiple instances.

for (i = 0; i < config->sub_mfd_node_num; i++) {
if (config->sub_mfd_dev[i] != NULL) {
if (config->sub_mfd_dev[i] == kbd_dev) {
it8801_input_alert_handler(config->sub_mfd_dev[i]);
Copy link
Contributor

Choose a reason for hiding this comment

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

This function isn't available in this commit. Each commit should build on it's own. Add this support with the KBD driver commit.

You could have the child drivers register an alert callback. Then MFD driver doesn't need to know the type of each child.

If you wanted the alert callbacks to be configured at build time, you could define an iterable section per it8801 instance.

See INPUT_CALL_DEFINE for an example of creating an iterable section for a specific device instance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Moved to respective driver.

Because the KBD and GPIO devices of IT8801 share the gpio irq. Consider that if IT8801 is connected to the EC, the GPIO interrupt is enabled in the interrupt configuration using irq_connect_dynamic.
Repeated registration of gpio irq will cause Assert problem, so here we only register it once in mfd_ite_it8801.


/ {
soc {
gpio0: gpiocr@0a {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nodename gpio0 is likely to conflict the the GPIO controller on the SoC.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Renamed.

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(input_ite_it8801_kbd, CONFIG_INPUT_LOG_LEVEL);

#define IT8801_MFDCTRL_COUNT IT8801_DT_INST_MFDCTRL_LEN(0)
Copy link
Contributor

Choose a reason for hiding this comment

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

This assumes only one KBD driver installed. This should be calculated on each KBD instance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed, use multiple instances.


static struct kbd_it8801_data kbd_it8801_data_0;

PM_DEVICE_DT_INST_DEFINE(0, input_kbd_matrix_pm_action);
Copy link
Contributor

Choose a reason for hiding this comment

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

Drivers should support multiple instances.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed, use multiple instances.

static struct pwm_it8801_data pwm_it8801_data_##inst; \
DEVICE_DT_INST_DEFINE(inst, &pwm_it8801_init, NULL, &pwm_it8801_data_##inst, \
&pwm_it8801_cfg_##inst, POST_KERNEL, \
CONFIG_PWM_IT8801_INIT_PRIORITY, &pwm_it8801_api);
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a BUILD_ASSERT that the init priority is lower (higher number) than the MFD parent.

Copy link
Member

Choose a reason for hiding this comment

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

I suggested in a separate comment that this could all use the same priority, then the sub priority would take care of sequencing the init correctly, I think it's a better approach, less options kicking around. Build asserts should not be needed anymore since the build priorites are checked at build time btw.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is there anything I can refer to here? I'm encountering a build error when using CONFIG_MFD_INIT_PRIORITY + 1 in Kconfig or here.

Comment on lines +19 to +20
IT8801 GPIO port device driver initialization priority. The priority
must be lower than MFD_INIT_PRIORITY device.
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a BUILD_ASSERT to check the init priority.

Copy link
Member

@fabiobaltieri fabiobaltieri left a comment

Choose a reason for hiding this comment

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

Just an quick initial, pass, noticed some comments of mine overlaps with Keith.

Hey is there a board where you could add this? I'm a bit confused by the dtsi file you have in one of the commits, would be nice to have build testing in CI as well.

struct mfd_it8801_data *data = dev->data;
int ret;

if (!device_is_ready(config->i2c_dev.bus)) {
Copy link
Member

Choose a reason for hiding this comment

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

you can use i2c_is_ready_dt

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

.i2c_dev = I2C_DT_SPEC_INST_GET(inst), \
.irq_gpios = GPIO_DT_SPEC_INST_GET(inst, irq_gpios), \
.sub_mfd_dev = sub_mfd_dev_##inst, \
.sub_mfd_node_num = DT_INST_CHILD_NUM(inst), \
Copy link
Member

Choose a reason for hiding this comment

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

wondering it would not be safer to use ARRAY_SIZE(sub_mfd_dev_##inst), just in case

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.

int i;

for (i = 0; i < config->sub_mfd_node_num; i++) {
if (config->sub_mfd_dev[i] != NULL) {
Copy link
Member

Choose a reason for hiding this comment

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

can this happen? I think it would fail the build if there's no actual device here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Redundant, removed.

Comment on lines +19 to +21
config MFD_IT8801_ALTCTRL_INIT_PRIORITY
int "IT8801 GPIO port init priority"
default 81
Copy link
Member

Choose a reason for hiding this comment

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

hey can you try to initialize all the sub devices at CONFIG_MFD_INIT_PRIORITY? the sub-priority should take care of the sequencing, less priority options kicking around... you can check the output with west build -t initlevels

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Is there anything I can refer to here? I'm encountering a build error when using CONFIG_MFD_INIT_PRIORITY + 1 here.

*/

/ {
soc {
Copy link
Member

Choose a reason for hiding this comment

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

This does not look quite right, how is this dtsi going to be used? the child nodes here should be child nodes of the mfd device, right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, this is the child node that mfd will use. Renamed.


struct pwm_it8801_data {
/* I2C device for the MFD parent */
const struct i2c_dt_spec *i2c_dev;
Copy link
Member

Choose a reason for hiding this comment

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

ite,it8801-pwm is a child node of the mfd device right? Then can you get this with DEVICE_DT_GET(DT_PARENT(...)) at build time?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's right, thanks for the tip, we can use this: I2C_DT_SPEC_GET(DT_INST_PARENT(inst))

static struct pwm_it8801_data pwm_it8801_data_##inst; \
DEVICE_DT_INST_DEFINE(inst, &pwm_it8801_init, NULL, &pwm_it8801_data_##inst, \
&pwm_it8801_cfg_##inst, POST_KERNEL, \
CONFIG_PWM_IT8801_INIT_PRIORITY, &pwm_it8801_api);
Copy link
Member

Choose a reason for hiding this comment

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

I suggested in a separate comment that this could all use the same priority, then the sub priority would take care of sequencing the init correctly, I think it's a better approach, less options kicking around. Build asserts should not be needed anymore since the build priorites are checked at build time btw.

The IT8801 is an I/O expander that provides GPIO, PWM, Keyboard
functions via the I2C bus.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
IT8801 support GPIO alternate function switching.
Some GPIO pins can be switched as KSO or PWM function.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
Add I2C-based keyboard matrix scan device driver.
IT8801 support 8 KSI pins and 19 KSO pins [22:11] [6:0].

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
Add I2C-based PWM device driver. Supports 7 open-drain/push-pull
outputs.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
Add I2C-based GPIO device driver. Supports 16-port GPIO divided
into 3 groups.

Signed-off-by: Tim Lin <tim2.lin@ite.corp-partner.google.com>
@GTLin08
Copy link
Collaborator Author

GTLin08 commented Oct 7, 2024

Just an quick initial, pass, noticed some comments of mine overlaps with Keith.

Hey is there a board where you could add this? I'm a bit confused by the dtsi file you have in one of the commits, would be nice to have build testing in CI as well.

I have created a test program to connect with it8xxx2_evb as shown in the link

@GTLin08
Copy link
Collaborator Author

GTLin08 commented Oct 7, 2024

Also consider running clang-format on all the files.

This is very strange. When using ./scripts/ci/check_compliance.py locally, there is a prompt such as:

You may want to run clang-format on this change

drivers/mfd/mfd_ite_it8801.c:133 
-		DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(inst, DEVICE_DT_GET, (,))};                  \
+		DT_INST_FOREACH_CHILD_STATUS_OKAY_SEP(inst, DEVICE_DT_GET, (, ))};                 \

But after I upload the program, I get the following error:

SPACING: space prohibited before that close parenthesis ')'
File:drivers/mfd/mfd_ite_it8801.c
Line:132

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: GPIO area: Input Input Subsystem and Drivers area: MFD area: PWM Pulse Width Modulation area: RISCV RISCV Architecture (32-bit & 64-bit) platform: ITE ITE
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants