drivers/mmc/host/sdhci-pci-gli.c

Source file repositories/reference/linux-study-clean/drivers/mmc/host/sdhci-pci-gli.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/host/sdhci-pci-gli.c
Extension
.c
Size
65471 bytes
Lines
2134
Domain
Driver Families
Bucket
drivers/mmc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!host->tuning_done) {
				sdhci_abort_tuning(host, opcode);
				break;
			}

			ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2);
			if (!(ctrl & SDHCI_CTRL_EXEC_TUNING)) {
				if (ctrl & SDHCI_CTRL_TUNED_CLK)
					return 0; /* Success! */
				break;
			}
		}
	}
	if (!host->tuning_done) {
		pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
			mmc_hostname(host->mmc));
		return -ETIMEDOUT;
	}

	pr_info("%s: Tuning failed, falling back to fixed sampling clock\n",
		mmc_hostname(host->mmc));
	sdhci_reset_tuning(host);

	return -EAGAIN;
}

static int gl9750_execute_tuning(struct sdhci_host *host, u32 opcode)
{
	host->mmc->retune_period = 0;
	if (host->tuning_mode == SDHCI_TUNING_MODE_1)
		host->mmc->retune_period = host->tuning_count;

	gli_set_9750(host);
	host->tuning_err = __sdhci_execute_tuning_9750(host, opcode);
	sdhci_end_tuning(host);

	return 0;
}

static void gl9750_disable_ssc_pll(struct sdhci_host *host)
{
	u32 pll;

	gl9750_wt_on(host);
	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
	pll &= ~(SDHCI_GLI_9750_PLL_DIR | SDHCI_GLI_9750_PLLSSC_EN);
	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
	gl9750_wt_off(host);
}

static void gl9750_set_pll(struct sdhci_host *host, u8 dir, u16 ldiv, u8 pdiv)
{
	u32 pll;

	gl9750_wt_on(host);
	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
	pll &= ~(SDHCI_GLI_9750_PLL_LDIV |
		 SDHCI_GLI_9750_PLL_PDIV |
		 SDHCI_GLI_9750_PLL_DIR);
	pll |= FIELD_PREP(SDHCI_GLI_9750_PLL_LDIV, ldiv) |
	       FIELD_PREP(SDHCI_GLI_9750_PLL_PDIV, pdiv) |
	       FIELD_PREP(SDHCI_GLI_9750_PLL_DIR, dir);
	sdhci_writel(host, pll, SDHCI_GLI_9750_PLL);
	gl9750_wt_off(host);

	/* wait for pll stable */
	mdelay(1);
}

static bool gl9750_ssc_enable(struct sdhci_host *host)
{
	u32 misc;
	u8 off;

	gl9750_wt_on(host);
	misc = sdhci_readl(host, SDHCI_GLI_9750_MISC);
	off = FIELD_GET(SDHCI_GLI_9750_MISC_SSC_OFF, misc);
	gl9750_wt_off(host);

	return !off;
}

static void gl9750_set_ssc(struct sdhci_host *host, u8 enable, u8 step, u16 ppm)
{
	u32 pll;
	u32 ssc;

	gl9750_wt_on(host);
	pll = sdhci_readl(host, SDHCI_GLI_9750_PLL);
	ssc = sdhci_readl(host, SDHCI_GLI_9750_PLLSSC);

Annotation

Implementation Notes