On Thu, 2023-06-01 at 12:00 +0200, AngeloGioacchino Del Regno wrote:
Yes, I think it's okay for me.
External email : Please do not click links or open attachments until
you have verified the sender or the content.
Il 01/06/23 05:16, Wenbin Mei (梅文彬) ha scritto:
On Wed, 2023-05-31 at 10:18 +0200, AngeloGioacchino Del Regnowrote:
External email : Please do not click links or open attachmentsuntil you have verified the sender or the content.
wrote:
Il 31/05/23 09:32, Wenbin Mei (梅文彬) ha scritto:
On Thu, 2023-05-18 at 11:13 +0200, AngeloGioacchino Del Regno
until
External email : Please do not click links or open attachments
decrease
you have verified the sender or the content.
Il 10/05/23 03:58, Wenbin Mei ha scritto:
CQHCI_SSC1 indicates to CQE the polling period to use when using
periodic
SEND_QUEUE_STATUS(CMD13) polling.
The default value 0x1000 that corresponds to 150us, let's
would
it to
The default value 0x1000 (4096) corresponds to 4096 * 52.08uS =
231.33uS
...so the default is not 150uS.
If I'm wrong, this means that the CQCAP field is not 0, which
we
mean
that the expected 3uS would be wrong.
Also, since the calculation can be done dynamically, this is what
you
should
actually do in the driver, as this gives information to the next
engineer
checking this piece of code.
Apart from this, by just writing 0x40 to the CQHCI_SSC1 register,
ITCFMUL
are
assuming that the CQCAP value requirement is fullfilled, but you
cannot
assume that the bootloader has set the CQCAP's ITCFVAL and
this
fields
as you expect on all platforms: this means that implementing this
takes
a little more effort.
You have two ways to implement this:
*** First ***
1. Read ITCFMUL and ITCFVAL, then:
tclk_mul = itcfmul_to_mhz(ITCFMUL); /* pseudo function
interprets reg value*/
tclk = ITCFVAL * tclk_mul;
2. Set SSC1 so that we get 3nS:
#define CQHCI_SSC1_CIT GENMASK(15, 0)
poll_time = cit_time_ns_to_regval(3);
sscit = FIELD_PREP(CQHCI_SSC1_CIT, poll_time)
cqhci_writel( ... )
*** Second **
1. Pre-set ITCFMUL and ITCFVAL to
ITCFVAL = 192 (decimal)
ITCFMUL = 2 (where 2 == 0.1MHz)
2. Set SSC1 so that we get 3nS:
#define CQHCI_SSC1_CIT GENMASK(15, 0)
poll_time = cit_time_ns_to_regval(3);
sscit = FIELD_PREP(CQHCI_SSC1_CIT, poll_time)
cqhci_writel( ... )
I would implement the first way, as it paves the way to extend
182,
to different
tclk values if needed in the future.
Regards,
Angelo
Hi Angelo,
Sorry for lately reply.
For Mediatek mmc host IP, ITCFMUL is 0x2(0x1MHz), ITVFVAL reports
since
and these fields are the same and are readonly for all IC, but
driver
Mediatek CQE uses msdc_hclk(273MHz), CMD13'interval calculation
reports RO.
should use 273MHz to get the actual time, so the actual clock is
27.3MHz.
You're right, I've misread the datasheet, just rechecked and it
ITCFMUL
If CIT is 0x1000 by default, CMD idle time: 0x1000 * 1 / 27.3MHz =
around 150us.
In addition the bootloader will not set the CQCAP's ITCFVAL and
we
fields, because these fields of CQCAP register is RO(readonly), so
first
can ignore the change for the CQCAP's ITCFVAL and ITCFMUL fields.
Yes, that's right, again - this means that you should go for the
change
proposed implementation, as future MediaTek SoCs may (or may not)
thing
that: if you implement as proposed, this is going to be a one-time
to
and future SoCs won't need specific changes.
That implementation also documents the flow about how we're getting
this
the actual value, which is important for community people reading
ITCFVAL and ITCFMUL will not change.
driver in the future for debugging purposes.
Regards,
Angelo
Thanks for your proposal.
I have discussed with our designer, and this fields of CQCAP's
If we add more code for it, these codes will also affect theexecution efficiency, even if it has a very
small effect.comments to make it easier to read the code.
I think if it's just for reading convenience, we can add mode
Do you think it's okay to add more comments?
This isn't a performance path, but anyway, if you think that it will
be at some
point, you can read the two registers at probe time as part of the
MMC_CAP2_CQE
if branch, and then cache the invariable values to `struct
msdc_host`: this
will make you able to never perform register reads for ITCFVAL/FMUL
in
msdc_cqe_enable(), resolving the efficiency issue.
Even better, instead of caching ITCFVAL/FMUL to two variables, since
the idle
timer value likely won't ever change during runtime, you can directly
perform
the calculation for SSC1 at probe time and cache that value instead,
so that
in msdc_cqe_enable() you will have something like...
/* Set the send status command idle timer */
cqhci_writel(cq_host, host->cq_ssc1_time, CQHCI_SSC1);
where cq_ssc1_time is
struct msdc_host {
.......
u32 cq_ssc1_time;
....
}
and where your probe function is
static int msdc_drv_probe(struct platform_device *pdev)
{
......
if (mmc->caps2 & MMC_CAP2_CQE) {
host->cq_host = ......
........
read itcfval;
read itcfmul;
host->cq_ssc1_time = calculated-value;
........
}
.......
}
Another problem, ITCFVAL reports 182 for MediaTek SoCs, but we can not
use it to calculate, as i said earlier, since our CQE uses
msdc_hclk(273MHz), CMD13' interval calculation drivers should use
273MHz to get the actual time, not 182MHz.
If we use ITCFVAL, we will get a wrong value.
So I think it's meaningless.
Begards,
Wenbin
Regards,
Angelo
Begards,of
Wenbin
Thanks
Wenbin
0x40 that corresponds to 3us, which can improve the performance
sd.c
some
eMMC devices.
Signed-off-by: Wenbin Mei <wenbin.mei@xxxxxxxxxxxx>
---
drivers/mmc/host/mtk-sd.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-
msdc_hs400_enhanced_strobe(struct
index edade0e54a0c..ffeccddcd028 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -2453,6 +2453,7 @@ static void
mmc_host
mmc_host *mmc,
static void msdc_cqe_enable(struct mmc_host *mmc)
{
struct msdc_host *host = mmc_priv(mmc);
+ struct cqhci_host *cq_host = mmc->cqe_private;
/* enable cmdq irq */
writel(MSDC_INT_CMDQ, host->base + MSDC_INTEN);
@@ -2462,6 +2463,9 @@ static void msdc_cqe_enable(struct
recovery)
*mmc)
msdc_set_busy_timeout(host, 20 * 1000000000ULL, 0);
/* default read data timeout 1s */
msdc_set_timeout(host, 1000000000ULL, 0);
+
+ /* decrease the send status command idle timer to 3us */
+ cqhci_writel(cq_host, 0x40, CQHCI_SSC1);
}
static void msdc_cqe_disable(struct mmc_host *mmc, bool