--- zzzz-none-000/linux-5.15.111/drivers/mmc/host/sdhci.h 2023-05-11 14:00:40.000000000 +0000 +++ puma7-atom-6670-761/linux-5.15.111/drivers/mmc/host/sdhci.h 2024-02-07 10:23:07.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 @@ -18,6 +26,9 @@ #include #include +#ifdef CONFIG_HW_MUTEXES +#include +#endif /* * Controller registers @@ -74,11 +85,13 @@ #define SDHCI_CD_STABLE 0x00020000 #define SDHCI_CD_LVL 0x00040000 #define SDHCI_CD_LVL_SHIFT 18 +#define SDHCI_CARD_IS_STABLE 0x00020000 #define SDHCI_WRITE_PROTECT 0x00080000 #define SDHCI_DATA_LVL_MASK 0x00F00000 #define SDHCI_DATA_LVL_SHIFT 20 #define SDHCI_DATA_0_LVL_MASK 0x00100000 #define SDHCI_CMD_LVL 0x01000000 +#define SDHCI_STATE_BUSY_MASK (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT) #define SDHCI_HOST_CONTROL 0x28 #define SDHCI_CTRL_LED 0x01 @@ -477,6 +490,9 @@ * block count. */ #define SDHCI_QUIRK2_USE_32BIT_BLK_CNT (1<<18) +/* Two or more processors access the controller, HW mutex is needed to avoid + control conflicts. */ +#define SDHCI_QUIRK2_HW_MUTEX (1<<19) int irq; /* Device IRQ */ void __iomem *ioaddr; /* Mapped address */ @@ -513,6 +529,7 @@ #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 */ +#define SDHCI_PANIC_SYNC (1<<17) /* AVM: Sync writes on panic */ unsigned int version; /* SDHCI spec. version */ @@ -598,6 +615,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 */ +#ifdef 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 +634,9 @@ u64 data_timeout; +#ifdef CONFIG_AVM_MMC_SDHCI_ERRORSTATS + atomic_t errcnt[16]; +#endif unsigned long private[] ____cacheline_aligned; }; @@ -816,4 +840,70 @@ void sdhci_set_data_timeout_irq(struct sdhci_host *host, bool enable); void __sdhci_set_timeout(struct sdhci_host *host, struct mmc_command *cmd); +void sdhci_clock_gating(struct sdhci_host *host, bool enable); + +#ifdef CONFIG_HW_MUTEXES +#define SDHCI_DISABLE_REGISTER_WRITE (1<<16) + +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_HW_MUTEXES */ + #endif /* __SDHCI_HW_H */