--- zzzz-none-000/linux-5.15.111/drivers/mmc/host/sdhci.h 2023-05-11 14:00:40.000000000 +0000 +++ puma7-arm-6670-761/linux-5.15.111/drivers/mmc/host/sdhci.h 2024-02-07 09:27:48.000000000 +0000 @@ -6,6 +6,14 @@ * * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. */ + +/* + * Includes Maxlinear's changes dated: 2022. + * Changed portions - Copyright 2020-2022 MaxLinear, Inc. + * Includes Intel Corporation's changes dated: 2017, 2018. + * Changed portions - Copyright 2017-2020 Intel Corporation. + */ + #ifndef __SDHCI_HW_H #define __SDHCI_HW_H @@ -19,6 +27,11 @@ #include +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) +#include +#include +#endif + /* * Controller registers */ @@ -74,6 +87,9 @@ #define SDHCI_CD_STABLE 0x00020000 #define SDHCI_CD_LVL 0x00040000 #define SDHCI_CD_LVL_SHIFT 18 +#ifdef CONFIG_ARCH_GEN3 +#define SDHCI_CARD_IS_STABLE 0x00020000 +#endif #define SDHCI_WRITE_PROTECT 0x00080000 #define SDHCI_DATA_LVL_MASK 0x00F00000 #define SDHCI_DATA_LVL_SHIFT 20 @@ -477,6 +493,13 @@ * block count. */ #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18) +#ifdef CONFIG_ARCH_GEN3 +/* Two or more processors access the controller, HW mutex is needed to avoid + control conflicts. */ +#define SDHCI_QUIRK2_HW_MUTEX (1<<19) +/* Don't execute HS200 tuning */ +#define SDHCI_QUIRK2_DONT_TUNE_HS200 (1<<20) +#endif int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -513,6 +536,10 @@ #define SDHCI_SIGNALING_330 (1<<14) /* Host is capable of 3.3V signaling */ #define SDHCI_SIGNALING_180 (1<<15) /* Host is capable of 1.8V signaling */ #define SDHCI_SIGNALING_120 (1<<16) /* Host is capable of 1.2V signaling */ +#ifdef CONFIG_ARCH_GEN3 +/* Two or more processors access the controller, HW Mutex is necessary to avoid confliction*/ +#define SDHCI_DISABLE_REGISTER_WRITE (1<<17) /* Disable write on Host Driver - for non-destructive initialization */ +#endif unsigned int version; /* SDHCI spec. version */ @@ -598,6 +625,10 @@ unsigned int tuning_count; /* Timer count for re-tuning */ unsigned int tuning_mode; /* Re-tuning mode supported by host */ unsigned int tuning_err; /* Error code for re-tuning */ +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + unsigned int irq_enable_count; /* Count to enable recursive locking */ +#endif + #define SDHCI_TUNING_MODE_1 0 #define SDHCI_TUNING_MODE_2 1 #define SDHCI_TUNING_MODE_3 2 @@ -613,6 +644,11 @@ u64 data_timeout; + +#ifdef CONFIG_ARCH_GEN3 + struct task_struct *irq_thread; +#endif + unsigned long private[] ____cacheline_aligned; }; @@ -816,4 +852,69 @@ void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable); void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + +void sdhci_clock_gating(struct sdhci_host *host, bool enable); + +static DEFINE_MUTEX(irq_count_mutex); + +#define SDHCI_HOST_SUPPORTS_HW_MUTEX(sdhci) \ + ((sdhci)->quirks2 & SDHCI_QUIRK2_HW_MUTEX) +#define MMC_HOST_SUPPORTS_HW_MUTEX(mmc) SDHCI_HOST_SUPPORTS_HW_MUTEX( ((struct sdhci_host*)mmc->private)) + +#define EMMC_HW_MUTEX_IS_LOCKED() hw_mutex_is_locked(HW_MUTEX_EMMC) + +/* + * MMC_LOCK_HW_MUTEX_INIT should be used in initializations, + * where work with irq has not yet started + */ +#define MMC_LOCK_HW_MUTEX_INIT(mmc) \ +do { \ + struct sdhci_host *sdhci = (struct sdhci_host*)mmc->private; \ + if (SDHCI_HOST_SUPPORTS_HW_MUTEX(sdhci)) \ + { \ + hw_mutex_lock(HW_MUTEX_EMMC); \ + sdhci_clock_gating(sdhci, 1); \ + sdhci->irq_enable_count++; \ + } \ +} while(0) + +#define MMC_LOCK_HW_MUTEX(mmc) \ +do { \ + struct sdhci_host *sdhci = (struct sdhci_host*)mmc->private; \ + if (SDHCI_HOST_SUPPORTS_HW_MUTEX(sdhci)) \ + { \ + hw_mutex_lock(HW_MUTEX_EMMC); \ + mutex_lock(&irq_count_mutex); \ + if (sdhci->irq_enable_count == 0) \ + { \ + mmc->mmc_force_part_switch = true; \ + sdhci_clock_gating(sdhci, 1); \ + enable_irq(sdhci->irq); \ + } \ + sdhci->irq_enable_count++; \ + mutex_unlock(&irq_count_mutex); \ + } \ +} while(0) + +#define MMC_UNLOCK_HW_MUTEX(mmc) \ +do{ \ + struct sdhci_host *sdhci = (struct sdhci_host*)mmc->private; \ + if (SDHCI_HOST_SUPPORTS_HW_MUTEX(sdhci)) \ + { \ + mutex_lock(&irq_count_mutex); \ + WARN_ON(sdhci->irq_enable_count == 0); \ + if (sdhci->irq_enable_count == 1) \ + { \ + disable_irq(sdhci->irq); \ + sdhci_clock_gating(sdhci, 0); \ + } \ + sdhci->irq_enable_count -= (sdhci->irq_enable_count == 0) ? 0 : 1; \ + mutex_unlock(&irq_count_mutex); \ + hw_mutex_unlock(HW_MUTEX_EMMC); \ + } \ +} while(0) + +#endif /* CONFIG_ARCH_GEN3 */ + #endif /* __SDHCI_HW_H */