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
ITE: drivers/spi: Add SPI Master driver module of ITE IT8XXX2 #53812
Conversation
137e0fb
to
185ec9f
Compare
ae22721
to
3918c0b
Compare
0 SSPI_MODE_0 Bit6 and Bit 5 are 00b | ||
1 SSPI_MODE_1 Bit6 and Bit 5 are 01b | ||
2 SSPI_MODE_2 Bit6 and Bit 5 are 10b | ||
3 SSPI_MODE_3 Bit6 and Bit 5 are 11b |
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.
what do these modes actually mean?
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.
Hi galak,
These constants represent the different clock phases which is defined as different modes and can be selected in the SPICTRL1 register.
Bit 6 of the SPICTRL1 represents the Clock Polarity (CLPOL)
0: SSCK is low in the idle mode
1: SSCK is high in the idle mode
Bit 5 of the SPICTRL1 represents the Clock Phase (CLPHS)
0: Latch data on the first SSCK edge
1: Latch data on the second SSCK edge
Therefore, it behaves as follows:
Mode 0:
SSCK is low in the idle mode. Data is sampled on the rising edge, and shifted on the falling edge.
Mode 1:
SSCK is low in the idle mode. Data is sampled on the falling edge, and shifted on the rising edge.
Mode 2:
SSCK is high in the idle mode. Data is sampled on the falling edge, and shifted on the rising edge.
Mode 3:
SSCK is high in the idle mode. Data is sampled on the rising edge, and shifted on the falling edge.
Thanks for feedbacks & Best regards,
BJ
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 would be better to document the SPI mode in terms of the CPOL (clock polarity) and CPHA (clock phase) parameters.
https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#Clock_polarity_and_phase
Some other drivers provide spi-cpol
and spi-cpha
properties.
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.
Dear Keith,
Thank you sir, I totally agree with that and I'll change the terms when I add the comments.
Secondly, are the spi-cpol and spi-cpha properties recommended methods of implementing this part?
Thanks & Warmest regards,
BJ
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.
Yes, please use spi-cpol
and spi-cpha
as your properties. Your driver will process the properties to set the correct SSPI_MODE setting required by the ITE SPI controller.
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.
Thanks for guidance, sir. I've modified the SPI mode to be spi-cpol and spi-cpha properties in this update.
0 SSPI_MODE_0 Bit6 and Bit 5 are 00b | ||
1 SSPI_MODE_1 Bit6 and Bit 5 are 01b | ||
2 SSPI_MODE_2 Bit6 and Bit 5 are 10b | ||
3 SSPI_MODE_3 Bit6 and Bit 5 are 11b |
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 would be better to document the SPI mode in terms of the CPOL (clock polarity) and CPHA (clock phase) parameters.
https://en.wikipedia.org/wiki/Serial_Peripheral_Interface#Clock_polarity_and_phase
Some other drivers provide spi-cpol
and spi-cpha
properties.
drivers/spi/spi_ite_it8xxx2.c
Outdated
it8xxx2_spi_cmdq_init(dev); | ||
it8xxx2_spi_configure_sckfreq(dev); | ||
it8xxx2_spi_configure_spimode(dev); | ||
it8xxx2_spi_int_init(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.
I think you need to call these functions for every SPI instance used, correct?
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.
Dear Keith,
Well, theoretically, yes. However, the SPI CE0 & CE1 shares these configurations because they share the same clock. Some configurations for both channels need to be added then. I'll update it in the next revision.
Thanks again for guidance, sir.
Best regards,
BJ
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 has been modified to be invoked for each instance but so far the IT8XXX2 would not have the spi1.
drivers/spi/spi_ite_it8xxx2.c
Outdated
static void spi_it8xxx2_isr(const struct device *dev) | ||
{ | ||
const struct spi_it8xxx2_config *cfg = dev->config; | ||
struct spi_it8xxx2_regs *const spi_regs = | ||
(struct spi_it8xxx2_regs *)cfg->base_addr; | ||
|
||
irq_disable(cfg->irq_no); | ||
|
||
spi_regs->INTSTS |= SPICMDQEND; | ||
ite_intc_isr_clear(cfg->irq_no); | ||
spi_regs->SPICTRL5 &= ~(CH1SELCMDQ | CH0SELCMDQ); | ||
k_sem_give(&it8xxx2_sem); | ||
chip_permit_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.
This ISR doesn't appear to support configurations where both SPI controllers are enabled. The 2nd SPI controller initialized will never generate or process any interrupts.
You likely need shared interrupt support as proposed in #49427.
The alternative here would be to use the DT_INST_FOREACH_STATUS_OKAY()
and DEVICE_DT_INST_GET()
to lookup the the struct device
for all SPI controllers, and check if there is pending interrupt on each controller. I think you would also need an semaphore for each SPI controller instance instead of shared global one.
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.
Dear Keith,
Sorry for delayed response coz we were in a long vacation of Lunar New Year.
Yes, I think that you're absolutely right, the interrupt connection only works for one instance.
For the instance 0 and 1 share the same interrupt number, I'm wondering if it's still possible to tell if there is pending interrupt on each controller.
I think that the #49427 which you mentioned matches the requirement we'd need here. In another way, we can utilize some registers to tell if it's instance 0 or 1 but when it comes to the irq connection in Zephyr kernel, the *dev and related structure seem delivered among layers will still stick to the instance 0. I'll back to this after some internal discussions.
Truly appreciative of your guidance & helps.
Warmest regards,
BJ
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.
See this example for how to handle a shared interrupt by two driver instances:
To adapt this to the ITE SPI driver, you would read the INTSTS register to determine if an interrupt is pending:
spi_it8xxx2_instance_isr(dev)
{
/* Clear interrupts, give semaphore, etc */
}
#define HANDLE_SHARED_IRQ(n, active_irq)
static const struct device *const dev_##n = DEVICE_DT_INST_GET(n);
const struct spi_it8xxx2_regs *spi_regs_##n = dev_##n->config->base_addr;;
if (spi_regs_##->INTSTS) {
spi_it8xxx2_instance_isr(dev_##);
}
void spi_it8xxx2_shared_isr(const struct device *dev)
{
ARG_UNUSED(dev);
DT_INST_FOREACH_STATUS_OKAY(HANDLE_SHARED_IRQ);
}
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.
Thank you, sir. We also found that our chip can only support spi0 according to the current pin numbers, only specific chip with more pins can support second instance but so far we don't have it. So the second instance has been removed in dtsi files. Though we keep the init style like multiple instance but it's just for the scalability in the future.
zephyr_library_sources_ifdef(CONFIG_SPI_ASYNC spi_signal.c) | ||
zephyr_library_sources_ifdef(CONFIG_SPI_ITE_IT8XXX2 spi_ite_it8xxx2.c) |
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.
Nitpick: This is a wrong place to add this line. IMO it should be added after line 36, and the blank line should separate this group from the more generic files (async, userspace etc.)
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.
Dear Filip,
Thanks for reminding, yes you're right. I'll correct this in the next upload.
Thanks again for helps.
Warmest regards,
BJ
This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time. |
Is it still possible to remove the label now? I'd really like to remove the Stale label and reopen this PR but I cannot see the reopen button below the comment field. |
@itebj This PR cannot be reopened since the branch was force-pushed after the PR was closed. If you can push the last SHA as seen in this PR, I might be able to reopen it. Otherwise you will need to create a new PR and reference this one. |
@henrikbrixandersen |
@henrikbrixandersen Thank you so much for reopening it, sir. I'll update it ASAP. |
055678b
to
e41f876
Compare
Added SPI driver supporting SPI master channels in command queue mode Signed-off-by: BJ Chen <bj.chen@ite.com.tw>
Dear sirs, This update removes the spi1 and replace spi-mode property with spi-cpol and spi-cpha. In the meanwhile, we also remove the ch1 related stuffs for the command queue mode usage. The initialization style remains for the future scalability. but this update still need some modifications, I'll update it ASAP. If there's any suggestion/advice, please kindly let me know about it. Best regards, |
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), | ||
spi_it8xxx2_isr, DEVICE_DT_INST_GET(0), 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.
Your code assumes SPI instance 0. You can use this instead.
IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), | |
spi_it8xxx2_isr, DEVICE_DT_INST_GET(0), 0); | |
IRQ_CONNECT(cfg->irq_no, cfg->irq_priority, spi_it8xxx2_isr, dev, 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.
Got it, sir. Actually I think that we'd add the multiple-instance declaration back, but for supporting ASYNC option, the arguments spi_callback_t cb & void *userdata should be listed in the _transceive_async api, so I'm now trying to figure out how to replace original semaphore declaration and usage with helper functions in spi_context.h. So far this case is kinda pending temporarily. Thanks for great patience and guidnace, sir.
Added SPI driver supporting SPI master channels in command queue mode
Signed-off-by: BJ Chen bj.chen@ite.com.tw