2015-12-23 14:39 GMT+08:00 Peter Guo <[email protected]>:
> Hi Ulf,
>
> Thanks for your suggestion, Please check my comment.
>
> BR
> Peter.guo
>
> -----Original Message-----
> From: Ulf Hansson [mailto:[email protected]]
> Sent: Tuesday, December 22, 2015 4:30 PM
> To: Peter Guo
> Cc: Alex Ballas; [email protected]; [email protected]; Adrian
> Hunter; Russell King - ARM Linux
> Subject: Re: 1217:8520 [Dell Latitude E7450] O2 Micro, SD/MMC Card Reader
> doesn't work
>
> + Adrian, Russell
>
> On 22 December 2015 at 04:24, Peter Guo <[email protected]> wrote:
>>> Hi Ulf & Alex,
>>>
>>> Below is the complete analysis of this issue.
>>>
>>> The basic flow of send command is as below:
>>> (1) Upper layer prepare the command parameter;
>>> (2) Call sdhci_send_command, and sdhci_send_command will call
>>> sdhci_set_transfer_mode to set Host Register 0xC;
>>> (3) Call sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),
>>> SDHCI_COMMAND) to send command;
>>>
>>> For Linux kernel mainstream (without any quirk), MMC case:
>>> (1) It will call mmc_get_ext_csd and this is an DMA transfer, then DMA
>>> enable bit will be set to 1 (0xC[0]=1'b1).
>>> (2) Then next Command is mmc_switch(cmd6) which is none-data command, the
>>> driver will keep DMA enable bit to 1; this will let our Host failed to
>>> execute the CMD06.
>>>
>>> According to SD Host Spec(SD Host Controller Specification verson 4.1 page
>>> 41):
>>> Bit0 of Transfer Mode Register(0x0C) is DMA Enable bit, this bit set to 1
>>> means a DMA operation shall begin when Host Driver writes to the upper
>>> byte of Command Register(0x0F).
>>>
>>> The DMA enable bit should be set to zero for this none-data command(CMD6).
>> Our host follow the spec. so I think it should be the sdhci driver’s issue
>> (sdhci_set_transfer_mode).
>>>
>>>
>>> So We tried SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD to fix above
>>> issue.
>
>>This quirk seems a bit strange. It looks like a generic problem being solved
>>by the wrong approach. Although, my knowledge of sdhci HW is limited so I
>>might be wrong.
>
>>Why doesn't sdhci *always* reset the related registers when the command or
>>data transfer gets *completed*? Instead as currently, delaying that until the
>>*next* request is started and via using
>>SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD?
>
> Yes, this is one solution. We can clear TRANSMER_MODE register(0xC) after SD
> cmd done to solve current issue, below is the change method:
> static void sdhci_tasklet_finish(unsigned long param) {
> .....
> host->mrq = NULL;
> host->cmd = NULL;
> host->data = NULL;
> sdhci_writew(host, 0x0, SDHCI_TRANSFER_MODE);//Add Clear Transfer
> Mode here
> .....
> }
>
> But the Disadvantage of this method is: Driver need do additional one
> register write operation after each command. Please check whether you can
> accept this change or not. Also it is looks weird to touch setting registers
> here.
I noticed your discussing since it is me to send this
SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD patch long time ago. :)
As I know, It is not necessary to clear this transfer mode register
for a normal workable host. But I must do this quirk for my abnormal
host behavior.
>
>>>
>>> But it encounter new problem as Alex reported for tuning command as tuning
>>> command flow in sdhci_execute_tuning function is:
>>> (1). cmd.data = NULL;
>>> (2). sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); (3).
>>> sdhci_send_command(host, &cmd); As data is null, this quirk will set
>>> 0x0C[0:15] to ALL zero before send tuning command including
>>> SDHCI_TRNS_READ, and the tuning command will failed.
>
>>I see.
>
>>Sdhci's sdhci_execute_tuning() function must be converted to use
>>mmc_send_tuning().
>
>>This means the regular request path will be maintained and thus no special
>>treatment should be needed.
>
>>Nevertheless, if my suggestions around changing sdhci's default behaviour
>>instead of using SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD, >perhaps you
>>don't need to fix sdhci_execute_tuning() to solve the error here!?
>
> I have checked the mmc_send_tuning flow, and it can't replace
> sdhci_execute_tuning because the tuning command for sdhci.c is special
> command compare with normal command for 2 points:
> (1) It don't generate Command Complete Interrupt(register 0x30 bit0)
> (2) It has no data for host driver to read but SDHCI_TRNS_READ flag need to
> be set.
>
Here it is reason why I did not met same issue with yours in tuning
mode when I am using this quirk, since I just use mmc_send_tuning to
do software tuning, which is precondition of using this quirk.
>>>
>>> So, can we commit one patch as below to fix this DMA enable bit for
>>> non-data command bug if you cannot accept add new QUIRK?
>
>>Nope, no new quirks.
>
>>> Code should like below(sdhci_set_transfer_mode):
>>> if (data == NULL) {
>>> if (host->quirks2 &
>>>
>>> SDHCI_QUIRK2_CLEAR_TRANSFERMODE_REG_BEFORE_CMD) {
>>> sdhci_writew(host, 0x0,
>>> SDHCI_TRANSFER_MODE);
>>> } else {
>>> /* clear Auto CMD settings for no data CMDs
>>> */
>>> mode = sdhci_readw(host,
>>> SDHCI_TRANSFER_MODE);
>>> sdhci_writew(host, mode &
>>> ~(SDHCI_TRNS_AUTO_CMD12 | SDHCI_TRNS_DMA /*Clear DMA enable bit also for
>>> no data CMDs*/
>>>
>>> SDHCI_TRNS_AUTO_CMD23), SDHCI_TRANSFER_MODE);
>>> }
>>> return;
>>> }
>
>>Thanks for the suggested solution, although I think this looks like yet
>>another hacky workaround for a generic problem.
>
>>Before I further consider that change, can you please look into my
>>suggestions above and see if any of those can simplify the solution?
>
>>[...]
>
>
> So my suggestion is:
> (1) mmc_send_tuning can't replace sdhci_execute_tuning as tuning command is
> special one;
> (2) modify the sdhci_set_transfer_mode to clear SDHCI_TRNS_DMA without quirk
> is better than clear transfer mode after command done. From my point of view,
> SDHCI_TRNS_DMA should be cleared for no-data command before issue command. It
> follows the spec.
>
>
> BR
> Peter.Guo
>
>
--
---
Vincent Wan(Zongshun)
www.mcuos.com
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html