The following patches add a QUIRK for enabling HISPD bit under special
conditions and set the QUIRK for am65x-evm.
Faiz Abbas (2):
mmc: sdhci: Add Quirk for enabling HISPD under special conditions
mmc: sdhci_am654: Add QUIRK2_TI_HISPD_BIT
drivers/mmc/host/sdhci.c | 36 ++++++++++++++++++++++------------
drivers/mmc/host/sdhci.h | 2 ++
drivers/mmc/host/sdhci_am654.c | 3 ++-
3 files changed, 28 insertions(+), 13 deletions(-)
--
2.19.2
Some controllers on TI devices requires the HISPD bit to be cleared
even in some high speed modes. Add a quirk that facilitates this
requirement.
Signed-off-by: Faiz Abbas <[email protected]>
---
drivers/mmc/host/sdhci.c | 36 ++++++++++++++++++++++++------------
drivers/mmc/host/sdhci.h | 2 ++
2 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index a8141ff9be03..ed4ed6054ddf 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -1916,18 +1916,30 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
- if (ios->timing == MMC_TIMING_SD_HS ||
- ios->timing == MMC_TIMING_MMC_HS ||
- ios->timing == MMC_TIMING_MMC_HS400 ||
- ios->timing == MMC_TIMING_MMC_HS200 ||
- ios->timing == MMC_TIMING_MMC_DDR52 ||
- ios->timing == MMC_TIMING_UHS_SDR50 ||
- ios->timing == MMC_TIMING_UHS_SDR104 ||
- ios->timing == MMC_TIMING_UHS_DDR50 ||
- ios->timing == MMC_TIMING_UHS_SDR25)
- ctrl |= SDHCI_CTRL_HISPD;
- else
- ctrl &= ~SDHCI_CTRL_HISPD;
+ if ((host->quirks2 & SDHCI_QUIRK2_TI_HISPD_BIT)) {
+ if (ios->timing == MMC_TIMING_MMC_HS400 ||
+ ios->timing == MMC_TIMING_MMC_HS200 ||
+ ios->timing == MMC_TIMING_MMC_DDR52 ||
+ ios->timing == MMC_TIMING_UHS_SDR50 ||
+ ios->timing == MMC_TIMING_UHS_SDR104 ||
+ ios->timing == MMC_TIMING_UHS_DDR50)
+ ctrl |= SDHCI_CTRL_HISPD;
+ else
+ ctrl &= ~SDHCI_CTRL_HISPD;
+ } else {
+ if (ios->timing == MMC_TIMING_SD_HS ||
+ ios->timing == MMC_TIMING_MMC_HS ||
+ ios->timing == MMC_TIMING_MMC_HS400 ||
+ ios->timing == MMC_TIMING_MMC_HS200 ||
+ ios->timing == MMC_TIMING_MMC_DDR52 ||
+ ios->timing == MMC_TIMING_UHS_SDR50 ||
+ ios->timing == MMC_TIMING_UHS_SDR104 ||
+ ios->timing == MMC_TIMING_UHS_DDR50 ||
+ ios->timing == MMC_TIMING_UHS_SDR25)
+ ctrl |= SDHCI_CTRL_HISPD;
+ else
+ ctrl &= ~SDHCI_CTRL_HISPD;
+ }
}
if (host->version >= SDHCI_SPEC_300) {
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
index 01002cba1359..aac026c5e184 100644
--- a/drivers/mmc/host/sdhci.h
+++ b/drivers/mmc/host/sdhci.h
@@ -485,6 +485,8 @@ struct sdhci_host {
* block count.
*/
#define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18)
+/* Some TI devices need the high speed bit disabled even in high speed modes */
+#define SDHCI_QUIRK2_TI_HISPD_BIT (1<<19)
int irq; /* Device IRQ */
void __iomem *ioaddr; /* Mapped address */
--
2.19.2
According to the AM654x Data Manual[1], the setup timing in lower speed
modes can only be met if the controller uses a falling edge data launch.
To ensure this, the HIGH_SPEED_ENA (HOST_CONTROL[2]) bit should be
cleared in default speed, SD high speed, MMC high speed, SDR12 and SDR25
speed modes.
Enable the SDHCI_QUIRK2_TI_HISPD_BIT quirk to facilitate this.
[1] http://www.ti.com/lit/gpn/am6546 Section 5.10.5.16.1
Signed-off-by: Faiz Abbas <[email protected]>
---
drivers/mmc/host/sdhci_am654.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/mmc/host/sdhci_am654.c b/drivers/mmc/host/sdhci_am654.c
index eea183e90f1b..739a91767d5a 100644
--- a/drivers/mmc/host/sdhci_am654.c
+++ b/drivers/mmc/host/sdhci_am654.c
@@ -172,7 +172,8 @@ static const struct sdhci_pltfm_data sdhci_am654_pdata = {
.ops = &sdhci_am654_ops,
.quirks = SDHCI_QUIRK_INVERTED_WRITE_PROTECT |
SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12,
- .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN,
+ .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
+ SDHCI_QUIRK2_TI_HISPD_BIT,
};
static int sdhci_am654_init(struct sdhci_host *host)
--
2.19.2
On 29/03/19 4:22 PM, Faiz Abbas wrote:
> Some controllers on TI devices requires the HISPD bit to be cleared
> even in some high speed modes. Add a quirk that facilitates this
> requirement.
Could you use sdhci I/O accessors for this?
>
> Signed-off-by: Faiz Abbas <[email protected]>
> ---
> drivers/mmc/host/sdhci.c | 36 ++++++++++++++++++++++++------------
> drivers/mmc/host/sdhci.h | 2 ++
> 2 files changed, 26 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
> index a8141ff9be03..ed4ed6054ddf 100644
> --- a/drivers/mmc/host/sdhci.c
> +++ b/drivers/mmc/host/sdhci.c
> @@ -1916,18 +1916,30 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
> ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
>
> if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
> - if (ios->timing == MMC_TIMING_SD_HS ||
> - ios->timing == MMC_TIMING_MMC_HS ||
> - ios->timing == MMC_TIMING_MMC_HS400 ||
> - ios->timing == MMC_TIMING_MMC_HS200 ||
> - ios->timing == MMC_TIMING_MMC_DDR52 ||
> - ios->timing == MMC_TIMING_UHS_SDR50 ||
> - ios->timing == MMC_TIMING_UHS_SDR104 ||
> - ios->timing == MMC_TIMING_UHS_DDR50 ||
> - ios->timing == MMC_TIMING_UHS_SDR25)
> - ctrl |= SDHCI_CTRL_HISPD;
> - else
> - ctrl &= ~SDHCI_CTRL_HISPD;
> + if ((host->quirks2 & SDHCI_QUIRK2_TI_HISPD_BIT)) {
> + if (ios->timing == MMC_TIMING_MMC_HS400 ||
> + ios->timing == MMC_TIMING_MMC_HS200 ||
> + ios->timing == MMC_TIMING_MMC_DDR52 ||
> + ios->timing == MMC_TIMING_UHS_SDR50 ||
> + ios->timing == MMC_TIMING_UHS_SDR104 ||
> + ios->timing == MMC_TIMING_UHS_DDR50)
> + ctrl |= SDHCI_CTRL_HISPD;
> + else
> + ctrl &= ~SDHCI_CTRL_HISPD;
> + } else {
> + if (ios->timing == MMC_TIMING_SD_HS ||
> + ios->timing == MMC_TIMING_MMC_HS ||
> + ios->timing == MMC_TIMING_MMC_HS400 ||
> + ios->timing == MMC_TIMING_MMC_HS200 ||
> + ios->timing == MMC_TIMING_MMC_DDR52 ||
> + ios->timing == MMC_TIMING_UHS_SDR50 ||
> + ios->timing == MMC_TIMING_UHS_SDR104 ||
> + ios->timing == MMC_TIMING_UHS_DDR50 ||
> + ios->timing == MMC_TIMING_UHS_SDR25)
> + ctrl |= SDHCI_CTRL_HISPD;
> + else
> + ctrl &= ~SDHCI_CTRL_HISPD;
> + }
> }
>
> if (host->version >= SDHCI_SPEC_300) {
> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
> index 01002cba1359..aac026c5e184 100644
> --- a/drivers/mmc/host/sdhci.h
> +++ b/drivers/mmc/host/sdhci.h
> @@ -485,6 +485,8 @@ struct sdhci_host {
> * block count.
> */
> #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18)
> +/* Some TI devices need the high speed bit disabled even in high speed modes */
> +#define SDHCI_QUIRK2_TI_HISPD_BIT (1<<19)
>
> int irq; /* Device IRQ */
> void __iomem *ioaddr; /* Mapped address */
>
Hi Adrian,
On 01/04/19 2:21 PM, Adrian Hunter wrote:
> On 29/03/19 4:22 PM, Faiz Abbas wrote:
>> Some controllers on TI devices requires the HISPD bit to be cleared
>> even in some high speed modes. Add a quirk that facilitates this
>> requirement.
>
> Could you use sdhci I/O accessors for this?
Can you elaborate? Not sure how this would be solved with
CONFIG_MMC_SDHCI_IO_ACCESSORS.
Thanks,
Faiz
>
>>
>> Signed-off-by: Faiz Abbas <[email protected]>
>> ---
>> drivers/mmc/host/sdhci.c | 36 ++++++++++++++++++++++++------------
>> drivers/mmc/host/sdhci.h | 2 ++
>> 2 files changed, 26 insertions(+), 12 deletions(-)
>>
>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>> index a8141ff9be03..ed4ed6054ddf 100644
>> --- a/drivers/mmc/host/sdhci.c
>> +++ b/drivers/mmc/host/sdhci.c
>> @@ -1916,18 +1916,30 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>> ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
>>
>> if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
>> - if (ios->timing == MMC_TIMING_SD_HS ||
>> - ios->timing == MMC_TIMING_MMC_HS ||
>> - ios->timing == MMC_TIMING_MMC_HS400 ||
>> - ios->timing == MMC_TIMING_MMC_HS200 ||
>> - ios->timing == MMC_TIMING_MMC_DDR52 ||
>> - ios->timing == MMC_TIMING_UHS_SDR50 ||
>> - ios->timing == MMC_TIMING_UHS_SDR104 ||
>> - ios->timing == MMC_TIMING_UHS_DDR50 ||
>> - ios->timing == MMC_TIMING_UHS_SDR25)
>> - ctrl |= SDHCI_CTRL_HISPD;
>> - else
>> - ctrl &= ~SDHCI_CTRL_HISPD;
>> + if ((host->quirks2 & SDHCI_QUIRK2_TI_HISPD_BIT)) {
>> + if (ios->timing == MMC_TIMING_MMC_HS400 ||
>> + ios->timing == MMC_TIMING_MMC_HS200 ||
>> + ios->timing == MMC_TIMING_MMC_DDR52 ||
>> + ios->timing == MMC_TIMING_UHS_SDR50 ||
>> + ios->timing == MMC_TIMING_UHS_SDR104 ||
>> + ios->timing == MMC_TIMING_UHS_DDR50)
>> + ctrl |= SDHCI_CTRL_HISPD;
>> + else
>> + ctrl &= ~SDHCI_CTRL_HISPD;
>> + } else {
>> + if (ios->timing == MMC_TIMING_SD_HS ||
>> + ios->timing == MMC_TIMING_MMC_HS ||
>> + ios->timing == MMC_TIMING_MMC_HS400 ||
>> + ios->timing == MMC_TIMING_MMC_HS200 ||
>> + ios->timing == MMC_TIMING_MMC_DDR52 ||
>> + ios->timing == MMC_TIMING_UHS_SDR50 ||
>> + ios->timing == MMC_TIMING_UHS_SDR104 ||
>> + ios->timing == MMC_TIMING_UHS_DDR50 ||
>> + ios->timing == MMC_TIMING_UHS_SDR25)
>> + ctrl |= SDHCI_CTRL_HISPD;
>> + else
>> + ctrl &= ~SDHCI_CTRL_HISPD;
>> + }
>> }
>>
>> if (host->version >= SDHCI_SPEC_300) {
>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>> index 01002cba1359..aac026c5e184 100644
>> --- a/drivers/mmc/host/sdhci.h
>> +++ b/drivers/mmc/host/sdhci.h
>> @@ -485,6 +485,8 @@ struct sdhci_host {
>> * block count.
>> */
>> #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18)
>> +/* Some TI devices need the high speed bit disabled even in high speed modes */
>> +#define SDHCI_QUIRK2_TI_HISPD_BIT (1<<19)
>>
>> int irq; /* Device IRQ */
>> void __iomem *ioaddr; /* Mapped address */
>>
>
On 1/04/19 12:01 PM, Faiz Abbas wrote:
> Hi Adrian,
>
> On 01/04/19 2:21 PM, Adrian Hunter wrote:
>> On 29/03/19 4:22 PM, Faiz Abbas wrote:
>>> Some controllers on TI devices requires the HISPD bit to be cleared
>>> even in some high speed modes. Add a quirk that facilitates this
>>> requirement.
>>
>> Could you use sdhci I/O accessors for this?
>
> Can you elaborate? Not sure how this would be solved with
> CONFIG_MMC_SDHCI_IO_ACCESSORS.
In ->writeb()
if (reg == SDHCI_HOST_CONTROL) {
if (host->mmc->ios->timing == whatever)
val &= ~SDHCI_CTRL_HISPD;
}
writeb(val, host->ioaddr + reg);
>
> Thanks,
> Faiz
>
>>
>>>
>>> Signed-off-by: Faiz Abbas <[email protected]>
>>> ---
>>> drivers/mmc/host/sdhci.c | 36 ++++++++++++++++++++++++------------
>>> drivers/mmc/host/sdhci.h | 2 ++
>>> 2 files changed, 26 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
>>> index a8141ff9be03..ed4ed6054ddf 100644
>>> --- a/drivers/mmc/host/sdhci.c
>>> +++ b/drivers/mmc/host/sdhci.c
>>> @@ -1916,18 +1916,30 @@ void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
>>> ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
>>>
>>> if (!(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) {
>>> - if (ios->timing == MMC_TIMING_SD_HS ||
>>> - ios->timing == MMC_TIMING_MMC_HS ||
>>> - ios->timing == MMC_TIMING_MMC_HS400 ||
>>> - ios->timing == MMC_TIMING_MMC_HS200 ||
>>> - ios->timing == MMC_TIMING_MMC_DDR52 ||
>>> - ios->timing == MMC_TIMING_UHS_SDR50 ||
>>> - ios->timing == MMC_TIMING_UHS_SDR104 ||
>>> - ios->timing == MMC_TIMING_UHS_DDR50 ||
>>> - ios->timing == MMC_TIMING_UHS_SDR25)
>>> - ctrl |= SDHCI_CTRL_HISPD;
>>> - else
>>> - ctrl &= ~SDHCI_CTRL_HISPD;
>>> + if ((host->quirks2 & SDHCI_QUIRK2_TI_HISPD_BIT)) {
>>> + if (ios->timing == MMC_TIMING_MMC_HS400 ||
>>> + ios->timing == MMC_TIMING_MMC_HS200 ||
>>> + ios->timing == MMC_TIMING_MMC_DDR52 ||
>>> + ios->timing == MMC_TIMING_UHS_SDR50 ||
>>> + ios->timing == MMC_TIMING_UHS_SDR104 ||
>>> + ios->timing == MMC_TIMING_UHS_DDR50)
>>> + ctrl |= SDHCI_CTRL_HISPD;
>>> + else
>>> + ctrl &= ~SDHCI_CTRL_HISPD;
>>> + } else {
>>> + if (ios->timing == MMC_TIMING_SD_HS ||
>>> + ios->timing == MMC_TIMING_MMC_HS ||
>>> + ios->timing == MMC_TIMING_MMC_HS400 ||
>>> + ios->timing == MMC_TIMING_MMC_HS200 ||
>>> + ios->timing == MMC_TIMING_MMC_DDR52 ||
>>> + ios->timing == MMC_TIMING_UHS_SDR50 ||
>>> + ios->timing == MMC_TIMING_UHS_SDR104 ||
>>> + ios->timing == MMC_TIMING_UHS_DDR50 ||
>>> + ios->timing == MMC_TIMING_UHS_SDR25)
>>> + ctrl |= SDHCI_CTRL_HISPD;
>>> + else
>>> + ctrl &= ~SDHCI_CTRL_HISPD;
>>> + }
>>> }
>>>
>>> if (host->version >= SDHCI_SPEC_300) {
>>> diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
>>> index 01002cba1359..aac026c5e184 100644
>>> --- a/drivers/mmc/host/sdhci.h
>>> +++ b/drivers/mmc/host/sdhci.h
>>> @@ -485,6 +485,8 @@ struct sdhci_host {
>>> * block count.
>>> */
>>> #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18)
>>> +/* Some TI devices need the high speed bit disabled even in high speed modes */
>>> +#define SDHCI_QUIRK2_TI_HISPD_BIT (1<<19)
>>>
>>> int irq; /* Device IRQ */
>>> void __iomem *ioaddr; /* Mapped address */
>>>
>>
>
Hi Adrian,
On 01/04/19 2:42 PM, Adrian Hunter wrote:
> On 1/04/19 12:01 PM, Faiz Abbas wrote:
>> Hi Adrian,
>>
>> On 01/04/19 2:21 PM, Adrian Hunter wrote:
>>> On 29/03/19 4:22 PM, Faiz Abbas wrote:
>>>> Some controllers on TI devices requires the HISPD bit to be cleared
>>>> even in some high speed modes. Add a quirk that facilitates this
>>>> requirement.
>>>
>>> Could you use sdhci I/O accessors for this?
>>
>> Can you elaborate? Not sure how this would be solved with
>> CONFIG_MMC_SDHCI_IO_ACCESSORS.
>
> In ->writeb()
>
> if (reg == SDHCI_HOST_CONTROL) {
> if (host->mmc->ios->timing == whatever)
> val &= ~SDHCI_CTRL_HISPD;
> }
>
> writeb(val, host->ioaddr + reg);
This is a really good idea. Will use it in v2. Thanks.
Regards,
Faiz