driver: add oob support for spi-rockchip and pl330#2
driver: add oob support for spi-rockchip and pl330#2StevenFryto wants to merge 10 commits intolinux-evl-6.1-stan-rkr4.1from
Conversation
…nterrupt from oob to inband stage
drivers/dma/pl330.c
Outdated
|
|
||
| /* To protect channel manipulation */ | ||
| spinlock_t lock; | ||
| hard_spinlock_t oob_lock; |
There was a problem hiding this comment.
Since the lock is not only used in oob-mode, should we change its name with prefix "oob_"?
ruiqurm
left a comment
There was a problem hiding this comment.
Hi. Thanks your contribution!
Overall, the basic logic of the code is sound. It's clear that you've put a great deal of thought into it, and the implementation of the core functions is quite clear, which is already good.
However, there are perhaps some minor details that could use a bit more polishing. I have left some comments, where you may get the idea.
| ret = 2; | ||
| } | ||
|
|
||
| if (!running_oob()) { |
There was a problem hiding this comment.
Should we handle the callback of descriptor that marked as DMA_OOB_INTERRUPT directly here?
There was a problem hiding this comment.
All descriptors that marked as DMA_OOB_INTERRUPT have been handled during the oob stage. I think we only need to maintain the origin logic of the driver in the inband stage.
|
|
||
| unsigned long mask = val; | ||
|
|
||
| // printk("pl330->pcfg.num_events = %d\n", pl330->pcfg.num_events); |
There was a problem hiding this comment.
Mayve we can handle the events only when running oob, so that you do not have to store the pending state?
There was a problem hiding this comment.
IMO the pending state is necessary because it is used to store and forward the event which should be handled in the inband stage. When running oob, we only need to handle the desc which is marked as DMA_OOB_INTERRUPT and DMA_OOB_PULSED , the other should be forward to inband.
drivers/dma/pl330.c
Outdated
| if (pl330_update(data)) | ||
| pr_info("------------------%s:%d------------------\n", __func__, __LINE__); | ||
| int state = pl330_update(data); | ||
| if (state == 1) |
There was a problem hiding this comment.
Maybe we could use other more readbale macro instead of some literals?
There was a problem hiding this comment.
ok, i will delete these unnecessary dbg info later.
There was a problem hiding this comment.
I mean the state == 2 is ambiguous if someone not read through your code.
drivers/dma/pl330.c
Outdated
| raw_spin_lock(&pch->thread->dmac->oob_lock); | ||
| // TODO: | ||
| dev_info(pch->dmac->ddma.dev, "%s:%d\n", __func__, __LINE__); | ||
| pl330_start_thread(pch->thread); |
There was a problem hiding this comment.
Could we use _trigger here? Since we can not afford to reset the dma on runtime, can we just panic or if there is some other unwind methods?
There was a problem hiding this comment.
I think using _trigger here is better and i will try later. For the second question, i notice that __trigger always returns True, maybe we can only judge the state of the dmac and dma channel by reading DS and ES registers.
drivers/spi/spi-rockchip.c
Outdated
| else | ||
| ROCKCHIP_SPI_SET_BITS(rs->regs + ROCKCHIP_SPI_SER, BIT(spi->chip_select)); | ||
|
|
||
| if (rs->cs_inactive) |
There was a problem hiding this comment.
IMO it is wired here. if we want to start the transfer, we should guarantee the cs is active. If not, maybe we should return some error code and some debug information.
There was a problem hiding this comment.
cs_inactive is only used in SPI slave mode. Since in the current EVL implementation, the out-of-band feature of the SPI controller is only effective in master mode, the use of cs_inactive here is indeed redundant. I will remove it.
| spi_enable_chip(rs, false); | ||
|
|
||
| struct spi_device *spi = xfer->spi; | ||
| if (spi_get_csgpiod(spi, 0)) |
| rockchip_spi_oob_config(rs, spi, xfer, ctlr->slave_abort); | ||
|
|
||
| // TODO: CS operation is more complex and need more design | ||
| if (spi_get_csgpiod(spi, 0)) |
| */ | ||
| if (rs->high_speed_state) { | ||
| if (rs->freq > IO_DRIVER_4MA_MAX_SCLK_OUT) | ||
| pinctrl_select_state(rs->dev->pins->p, |
There was a problem hiding this comment.
Note that pinctrl_select_state might utilize an inband lock in this context, as can be seen in the pinctrl_commit_state function. However, typically this function is called only once. As a result, the likelihood of a priority inversion incident occurring is quite low.
| * If speed is larger than IO_DRIVER_4MA_MAX_SCLK_OUT, | ||
| * set higher driver strength. | ||
| */ | ||
| if (rs->high_speed_state) { |
There was a problem hiding this comment.
A majority of the current configuration is for general setup purposes. Is it possible to make certain assumptions and simplify the function?
For instance, does our use case involve the high_speed_state? If it does, we need to retain this part. If not, can we put it in our prepare function?
There was a problem hiding this comment.
Since the current EVL out-of-band SPI framework supports full-duplex out-of-band communication only when the SPI controller is in master mode, I think we should remove configurations related to slave mode. Also, since DMA is mandatory, we should enable the relevant DMA settings by default. As for other configurations that do not conflict with these two points, we might as well keep them for now to make the most of the SPI controller’s capabilities.
There’s no need to place high_speed_state in the prepare function. The start function is also executed in-band, so it won’t affect real-time performance.
1. change pl330_dmac.pool_lock from hard_spinlock to spinlock, because it will never be used OOB; 2. change pl330_dmac.oob_lock and dma_pl330_chan.oob_lock from hard_spinlock to hybrid_spinlock; 3. fix the bug that desc's oob flag will influence inband spi transfer; 4. replace `pl330_start_thread` with `_trigger` in pl330_pulse_oob; 5. add marco to clarify the result of `pl330_update`.
This patch introduces out-of-band (OOB) pulse transmission support for the spi-rockchip driver and implements OOB mode for the pl330 DMA controller.
The implementation has been verified using the oob-spi example provided in libevl.
However, there are still several areas that require further improvement:
1.Code cleanup and addition of corresponding Kconfig entries.
2.The flag value should be cleared when recycling DMA descriptors, to prevent in-band SPI from accidentally using descriptors marked with out-of-band flags.
3.The granularity of dma_pulse_oob can be further refined.
4.The logic for enabling the chip select signal may need additional improvements.
5.The accuracy of rockchip_spi_pulse_oob_transfer still needs further evaluation.