- Notifications
You must be signed in to change notification settings - Fork 8.2k
drivers: add i2c driver support for MSPM0 #94627
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
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This driver needs lot of re-factor. In summary,
- ISR context is handling all the data path, which needs to be abstracted.
- Target and Controller support needs to be split.
- Multi target support needs to be compile time based on devicetree target nodes.
- Current usage of data section is high and needs to be optimized based on rodata / data place-holding.
Current code base is not compilable as well. So IMO it makes sense to put in DRAFT until it's ready for review.
teburd left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's some confusing things going on, maybe because the HAL is handling interrupts? It's unclear, but those should be handled by Zephyr not by the HAL if that's the case.
drivers/i2c/i2c_mspm0.c Outdated
| DL_I2C_startControllerTransfer(config->base, data->addr, DL_I2C_CONTROLLER_DIRECTION_TX, | ||
| data->msg.len); | ||
| | ||
| while (!(DL_I2C_getControllerStatus(config->base) & DL_I2C_CONTROLLER_STATUS_IDLE)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tight polling loops like this aren't inherently wrong but typically there's an interrupt signal available.
Would recommend changing the driver, if possible, to use an interrupt (event driven) state machine that is kicked off by the transfer function, and completed when the state machine signals back to the thread that had called transfer blocking on a k_sem_take by giving a semaphore.
If you really want the tight poll loop here instead, or there's no other option, use a WAIT_FOR() macro with a timeout such that even given a faulty i2c transfer the caller isn't blocked forever and instead may get an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking into refactoring transfer to use semaphores
| while (!(DL_I2C_getControllerStatus(config->base) & DL_I2C_CONTROLLER_STATUS_IDLE)) { | ||
| } | ||
| | ||
| if (data->state == I2C_MSPM0_TIMEOUT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And I maybe spoke too soon if there's a hardware timeout available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a configurable SCL low hardware timeout available
| reg: | ||
| required: true | ||
| | ||
| interrupts: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the interrupts being used?
| #address-cells = <1>; | ||
| #size-cells = <0>; | ||
| reg = <0x400f2000 0x2000>; | ||
| interrupts = <26 0>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't seem like the driver supports interrupts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interrupts are used for controller and target logic
The code base is compliable. Target support is split and optional from controller via kconfig define. Multi target support is compile time based on Kconfig defines |
1f122c6 to b708dc5 Compare | @teburd Ping for re-review. Refactored transmit logic to use semaphores instead of busy wait looping |
tbursztyka left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ISR handler would gain in clarity being split: irq types handled in dedicated inline functions and as noted already: target stuff being on their own as well.
| The following west manifest projects have changed revision in this Pull Request:
✅ All manifest checks OK Note: This message is automatically posted and updated by the Manifest GitHub Action. |
| @teburd @tbursztyka @ssekar15 Please review |
| @teburd ping for re-review, updated manifest |
parthitce left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Am still having a closer look.
drivers/i2c/i2c_mspm0.c Outdated
| struct i2c_msg transaction_msg; | ||
| int ret = 0; | ||
| | ||
| k_sem_take(data->i2c_busy_sem, K_FOREVER); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO there is no real protection against the target mode here. Move below the is_target condition check?
drivers/i2c/i2c_mspm0.c Outdated
| uint32_t speed_config; | ||
| | ||
| /* Init power */ | ||
| DL_I2C_reset(config->base); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure reset before enabling power will work
drivers/i2c/i2c_mspm0.c Outdated
| ret = clock_control_get_rate(clk_dev, (clock_control_subsys_t)config->clock_subsys, | ||
| &clock_rate); | ||
| if (ret < 0) { | ||
| ret = -ENODEV; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
propagate the clock error instead?
| goto out; | ||
| } | ||
| | ||
| if (dev_config & I2C_MSG_ADDR_10_BITS) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this sanity check can be done as entry into the function and return directly
| ti,pwm-mode = "EDGE_ALIGN"; | ||
| ti,period = <1000>; | ||
| }; | ||
| |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO this commit can be dropped. Sample or App can decide the whole usage in dts, pins and Kconfig. Doesn't needs to be enabled by default.
| | ||
| / { | ||
| soc { | ||
| i2c0: i2c@400f0000 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we keep the common i2c which is available across all series in mspm0.dtsi?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
future mspm0 devices will not all have base i2c0 peripheral
| @@ -0,0 +1,814 @@ | |||
| /* | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bindings is not part of this commit. either adjust the commit message or add the bindings file here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
amended
| return 0; | ||
| } | ||
| | ||
| static int i2c_mspm0_reset_peripheral_target(const struct device *dev) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall we instead wrap this with recover_bus and leave the decision to consumer?
| struct i2c_target_config *target_config; | ||
| const struct i2c_target_callbacks *target_callbacks; | ||
| #endif /* CONFIG_I2C_TARGET */ | ||
| bool is_target; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be dropped IMO
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is_target is used during runtime for apis and ISRs
drivers/i2c/i2c_mspm0.c Outdated
| goto out; | ||
| } | ||
| | ||
| k_sem_take(data->i2c_busy_sem, K_FOREVER); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Protecting the controller / IP as a resource doesn't need to lock for the whole function. Applies everywhere.
| { | ||
| struct i2c_mspm0_data *data = dev->data; | ||
| *dev_config = data->dev_config; | ||
| return 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the i2c is not configured, this API shall return error as per API description
| data->dev_config = dev_config; | ||
| | ||
| #if (CONFIG_I2C_SCL_LOW_TIMEOUT != 0) | ||
| ret = i2c_mspm0_configure_timeout(dev, period, CONFIG_I2C_SCL_LOW_TIMEOUT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
proceeding on error?
| DL_I2C_setTargetOwnAddress(config->base, data->target_config->address); | ||
| DL_I2C_setTargetTXFIFOThreshold(config->base, DL_I2C_TX_FIFO_LEVEL_BYTES_1); | ||
| DL_I2C_setTargetRXFIFOThreshold(config->base, DL_I2C_RX_FIFO_LEVEL_BYTES_1); | ||
| DL_I2C_enableTargetTXTriggerInTXMode(config->base); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but the trigger levels aren't handled in ISR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The FIFO trigger interrupts are used in the ISR
46a5870 to 04a2416 Compare Changes default pin properties for I2C. Signed-off-by: Dylan Philpot <d-philpot@ti.com>
Includes driver implementation for I2C controller and peripheral support. Signed-off-by: Dylan Philpot <d-philpot@ti.com>
Adds devicetree entries for different I2C peripherals on MSPM0 devices and dts binding changes for I2C driver. Signed-off-by: Dylan Philpot <d-philpot@ti.com>
|



Adds I2C controller and target support for MSPM0. Includes driver changes, dts and board updates.