--- zzzz-none-000/linux-5.15.111/drivers/mmc/host/sdhci-acpi.c 2023-05-11 14:00:40.000000000 +0000 +++ puma7-arm-6670-761/linux-5.15.111/drivers/mmc/host/sdhci-acpi.c 2024-02-07 09:27:48.000000000 +0000 @@ -2,7 +2,22 @@ /* * Secure Digital Host Controller Interface ACPI driver. * - * Copyright (c) 2012, Intel Corporation. + * Copyright 2020-2022, MaxLinear, Inc. + * Copyright 2012-2020, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. + * */ #include @@ -219,6 +234,32 @@ usleep_range(300, 1000); } +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) +void puma7_write_l(struct sdhci_host *host, u32 val, int reg) +{ + if (!(host->flags & SDHCI_DISABLE_REGISTER_WRITE)) + writel(val, host->ioaddr + reg); +} + +void puma7_write_w(struct sdhci_host *host, u16 val, int reg) +{ + if (!(host->flags & SDHCI_DISABLE_REGISTER_WRITE)) + writew(val, host->ioaddr + reg); +} + +void puma7_write_b(struct sdhci_host *host, u8 val, int reg) +{ + if (!(host->flags & SDHCI_DISABLE_REGISTER_WRITE)) + writeb(val, host->ioaddr + reg); +} + +unsigned int sdhci_acpi_puma7_get_min_clock(struct sdhci_host *host) +{ + /* PUMA7 host controllers only support down to 200kHz */ + return 200000; +} +#endif + static const struct sdhci_ops sdhci_acpi_ops_dflt = { .set_clock = sdhci_set_clock, .set_bus_width = sdhci_set_bus_width, @@ -234,10 +275,30 @@ .hw_reset = sdhci_acpi_int_hw_reset, }; +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) +static const struct sdhci_ops sdhci_acpi_ops_int_puma7_emmc = { + .set_clock = sdhci_set_clock, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, + .hw_reset = sdhci_acpi_int_hw_reset, + .get_min_clock = sdhci_acpi_puma7_get_min_clock, + .write_l = puma7_write_l, + .write_w = puma7_write_w, + .write_b = puma7_write_b, +#endif +}; + static const struct sdhci_acpi_chip sdhci_acpi_chip_int = { .ops = &sdhci_acpi_ops_int, }; +#ifdef CONFIG_ARCH_GEN3 +static const struct sdhci_acpi_chip sdhci_acpi_chip_int_puma7_emmc = { + .ops = &sdhci_acpi_ops_int_puma7_emmc, +}; +#endif + #ifdef CONFIG_X86 static bool sdhci_acpi_byt(void) @@ -441,6 +502,33 @@ .priv_size = sizeof(struct intel_host), }; +#ifdef CONFIG_ARCH_GEN3 +static const struct sdhci_acpi_slot sdhci_acpi_slot_int_puma7_emmc1 = { + .chip = &sdhci_acpi_chip_int_puma7_emmc, + .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | + MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | + MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY, + .caps2 = MMC_CAP2_NO_SHUTDOWN_BUS, + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_STOP_WITH_TC | + SDHCI_QUIRK2_HW_MUTEX, + .probe_slot = intel_probe_slot, +}; + +static const struct sdhci_acpi_slot sdhci_acpi_slot_int_puma7_emmc2 = { + .chip = &sdhci_acpi_chip_int_puma7_emmc, + .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE | + MMC_CAP_HW_RESET | MMC_CAP_1_8V_DDR | + MMC_CAP_CMD_DURING_TFR | MMC_CAP_WAIT_WHILE_BUSY, + .flags = SDHCI_ACPI_RUNTIME_PM, + .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN | + SDHCI_QUIRK2_STOP_WITH_TC, + .probe_slot = intel_probe_slot, +}; +#endif + static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sdio = { .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | SDHCI_QUIRK_NO_LED | @@ -456,12 +544,20 @@ }; static const struct sdhci_acpi_slot sdhci_acpi_slot_int_sd = { +#ifdef CONFIG_ARCH_GEN3 + .flags = SDHCI_ACPI_RUNTIME_PM, +#else .flags = SDHCI_ACPI_SD_CD | SDHCI_ACPI_SD_CD_OVERRIDE_LEVEL | SDHCI_ACPI_RUNTIME_PM, +#endif .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC | SDHCI_QUIRK_NO_LED, +#ifdef CONFIG_ARCH_GEN3 + .quirks2 = SDHCI_QUIRK2_STOP_WITH_TC, +#else .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON | SDHCI_QUIRK2_STOP_WITH_TC, +#endif .caps = MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_AGGRESSIVE_PM, .probe_slot = intel_probe_slot, .setup_host = intel_setup_host, @@ -762,6 +858,11 @@ { "80860F14" , "2" , &sdhci_acpi_slot_int_sdio }, { "80860F14" , "3" , &sdhci_acpi_slot_int_sd }, { "80860F16" , NULL, &sdhci_acpi_slot_int_sd }, +#ifdef CONFIG_ARCH_GEN3 + { "80862B94" , "1" , &sdhci_acpi_slot_int_puma7_emmc1 }, + { "80862B95" , "1" , &sdhci_acpi_slot_int_puma7_emmc2 }, + { "80862B96" , "1" , &sdhci_acpi_slot_int_sd }, +#endif { "INT33BB" , "2" , &sdhci_acpi_slot_int_sdio }, { "INT33BB" , "3" , &sdhci_acpi_slot_int_sd }, { "INT33C6" , NULL, &sdhci_acpi_slot_int_sdio }, @@ -782,6 +883,9 @@ { "80865AD0" }, { "80860F14" }, { "80860F16" }, +#ifdef CONFIG_ARCH_GEN3 + { "80862B94" }, +#endif { "INT33BB" }, { "INT33C6" }, { "INT3436" }, @@ -860,6 +964,9 @@ size_t priv_size; int quirks = 0; int err; +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + bool have_hw_mutex = FALSE; +#endif device = ACPI_COMPANION(dev); if (!device) @@ -962,6 +1069,14 @@ host->mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; } +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + if (SDHCI_HOST_SUPPORTS_HW_MUTEX(host)) { + MMC_LOCK_HW_MUTEX_INIT(host->mmc); + host->flags |= SDHCI_DISABLE_REGISTER_WRITE; + have_hw_mutex = TRUE; + } +#endif + err = sdhci_setup_host(host); if (err) goto err_free; @@ -973,6 +1088,15 @@ } err = __sdhci_add_host(host); + +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + if (SDHCI_HOST_SUPPORTS_HW_MUTEX(host)) { + host->flags &= ~SDHCI_DISABLE_REGISTER_WRITE; + MMC_UNLOCK_HW_MUTEX(host->mmc); + have_hw_mutex = FALSE; + } +#endif + if (err) goto err_cleanup; @@ -991,6 +1115,13 @@ err_cleanup: sdhci_cleanup_host(c->host); err_free: +#if (defined(CONFIG_ARCH_GEN3) && defined(CONFIG_HW_MUTEXES)) + if (have_hw_mutex && SDHCI_HOST_SUPPORTS_HW_MUTEX(host)) { + host->flags &= ~SDHCI_DISABLE_REGISTER_WRITE; + MMC_UNLOCK_HW_MUTEX(host->mmc); + have_hw_mutex = FALSE; + } +#endif if (c->slot && c->slot->free_slot) c->slot->free_slot(pdev);