From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 13 May 2024 10:30:14 +0000 Subject: [PATCH] modify sin led gpio --- kernel/drivers/mmc/host/sdhci-iproc.c | 123 ++++++++++++++++++++++++++++++++++------ 1 files changed, 104 insertions(+), 19 deletions(-) diff --git a/kernel/drivers/mmc/host/sdhci-iproc.c b/kernel/drivers/mmc/host/sdhci-iproc.c index a533ba9..b9eb2ec 100644 --- a/kernel/drivers/mmc/host/sdhci-iproc.c +++ b/kernel/drivers/mmc/host/sdhci-iproc.c @@ -15,6 +15,7 @@ * iProc SDHCI platform driver */ +#include <linux/acpi.h> #include <linux/delay.h> #include <linux/module.h> #include <linux/mmc/host.h> @@ -162,9 +163,36 @@ sdhci_iproc_writel(host, newval, reg & ~3); } +static unsigned int sdhci_iproc_get_max_clock(struct sdhci_host *host) +{ + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + + if (pltfm_host->clk) + return sdhci_pltfm_clk_get_max_clock(host); + else + return pltfm_host->clock; +} + +/* + * There is a known bug on BCM2711's SDHCI core integration where the + * controller will hang when the difference between the core clock and the bus + * clock is too great. Specifically this can be reproduced under the following + * conditions: + * + * - No SD card plugged in, polling thread is running, probing cards at + * 100 kHz. + * - BCM2711's core clock configured at 500MHz or more + * + * So we set 200kHz as the minimum clock frequency available for that SoC. + */ +static unsigned int sdhci_iproc_bcm2711_get_min_clock(struct sdhci_host *host) +{ + return 200000; +} + static const struct sdhci_ops sdhci_iproc_ops = { .set_clock = sdhci_set_clock, - .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_max_clock = sdhci_iproc_get_max_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, @@ -178,7 +206,7 @@ .write_w = sdhci_iproc_writew, .write_b = sdhci_iproc_writeb, .set_clock = sdhci_set_clock, - .get_max_clock = sdhci_pltfm_clk_get_max_clock, + .get_max_clock = sdhci_iproc_get_max_clock, .set_bus_width = sdhci_set_bus_width, .reset = sdhci_reset, .set_uhs_signaling = sdhci_set_uhs_signaling, @@ -250,27 +278,80 @@ .mmc_caps = 0x00000000, }; +static const struct sdhci_ops sdhci_iproc_bcm2711_ops = { + .read_l = sdhci_iproc_readl, + .read_w = sdhci_iproc_readw, + .read_b = sdhci_iproc_readb, + .write_l = sdhci_iproc_writel, + .write_w = sdhci_iproc_writew, + .write_b = sdhci_iproc_writeb, + .set_clock = sdhci_set_clock, + .set_power = sdhci_set_power_and_bus_voltage, + .get_max_clock = sdhci_iproc_get_max_clock, + .get_min_clock = sdhci_iproc_bcm2711_get_min_clock, + .set_bus_width = sdhci_set_bus_width, + .reset = sdhci_reset, + .set_uhs_signaling = sdhci_set_uhs_signaling, +}; + +static const struct sdhci_pltfm_data sdhci_bcm2711_pltfm_data = { + .quirks = SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12, + .ops = &sdhci_iproc_bcm2711_ops, +}; + +static const struct sdhci_iproc_data bcm2711_data = { + .pdata = &sdhci_bcm2711_pltfm_data, + .mmc_caps = MMC_CAP_3_3V_DDR, +}; + static const struct of_device_id sdhci_iproc_of_match[] = { { .compatible = "brcm,bcm2835-sdhci", .data = &bcm2835_data }, + { .compatible = "brcm,bcm2711-emmc2", .data = &bcm2711_data }, { .compatible = "brcm,sdhci-iproc-cygnus", .data = &iproc_cygnus_data}, { .compatible = "brcm,sdhci-iproc", .data = &iproc_data }, { } }; MODULE_DEVICE_TABLE(of, sdhci_iproc_of_match); +#ifdef CONFIG_ACPI +/* + * This is a duplicate of bcm2835_(pltfrm_)data without caps quirks + * which are provided by the ACPI table. + */ +static const struct sdhci_pltfm_data sdhci_bcm_arasan_data = { + .quirks = SDHCI_QUIRK_BROKEN_CARD_DETECTION | + SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | + SDHCI_QUIRK_NO_HISPD_BIT, + .quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN, + .ops = &sdhci_iproc_32only_ops, +}; + +static const struct sdhci_iproc_data bcm_arasan_data = { + .pdata = &sdhci_bcm_arasan_data, +}; + +static const struct acpi_device_id sdhci_iproc_acpi_ids[] = { + { .id = "BRCM5871", .driver_data = (kernel_ulong_t)&iproc_cygnus_data }, + { .id = "BRCM5872", .driver_data = (kernel_ulong_t)&iproc_data }, + { .id = "BCM2847", .driver_data = (kernel_ulong_t)&bcm_arasan_data }, + { .id = "BRCME88C", .driver_data = (kernel_ulong_t)&bcm2711_data }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(acpi, sdhci_iproc_acpi_ids); +#endif + static int sdhci_iproc_probe(struct platform_device *pdev) { - const struct of_device_id *match; - const struct sdhci_iproc_data *iproc_data; + struct device *dev = &pdev->dev; + const struct sdhci_iproc_data *iproc_data = NULL; struct sdhci_host *host; struct sdhci_iproc_host *iproc_host; struct sdhci_pltfm_host *pltfm_host; int ret; - match = of_match_device(sdhci_iproc_of_match, &pdev->dev); - if (!match) - return -EINVAL; - iproc_data = match->data; + iproc_data = device_get_match_data(dev); + if (!iproc_data) + return -ENODEV; host = sdhci_pltfm_init(pdev, iproc_data->pdata, sizeof(*iproc_host)); if (IS_ERR(host)) @@ -285,19 +366,21 @@ if (ret) goto err; - sdhci_get_of_property(pdev); + sdhci_get_property(pdev); host->mmc->caps |= iproc_host->data->mmc_caps; - pltfm_host->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(pltfm_host->clk)) { - ret = PTR_ERR(pltfm_host->clk); - goto err; - } - ret = clk_prepare_enable(pltfm_host->clk); - if (ret) { - dev_err(&pdev->dev, "failed to enable host clk\n"); - goto err; + if (dev->of_node) { + pltfm_host->clk = devm_clk_get(dev, NULL); + if (IS_ERR(pltfm_host->clk)) { + ret = PTR_ERR(pltfm_host->clk); + goto err; + } + ret = clk_prepare_enable(pltfm_host->clk); + if (ret) { + dev_err(dev, "failed to enable host clk\n"); + goto err; + } } if (iproc_host->data->pdata->quirks & SDHCI_QUIRK_MISSING_CAPS) { @@ -312,7 +395,8 @@ return 0; err_clk: - clk_disable_unprepare(pltfm_host->clk); + if (dev->of_node) + clk_disable_unprepare(pltfm_host->clk); err: sdhci_pltfm_free(pdev); return ret; @@ -323,6 +407,7 @@ .name = "sdhci-iproc", .probe_type = PROBE_PREFER_ASYNCHRONOUS, .of_match_table = sdhci_iproc_of_match, + .acpi_match_table = ACPI_PTR(sdhci_iproc_acpi_ids), .pm = &sdhci_pltfm_pmops, }, .probe = sdhci_iproc_probe, -- Gitblit v1.6.2