drivers/power/reset/at91-sama5d2_shdwc.c

Source file repositories/reference/linux-study-clean/drivers/power/reset/at91-sama5d2_shdwc.c

File Facts

System
Linux kernel
Corpus path
drivers/power/reset/at91-sama5d2_shdwc.c
Extension
.c
Size
11253 bytes
Lines
457
Domain
Driver Families
Bucket
drivers/power
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

struct shdwc_reg_config {
	u8 wkup_pin_input;
	u8 mr_rtcwk_shift;
	u8 mr_rttwk_shift;
	u8 sr_rtcwk_shift;
	u8 sr_rttwk_shift;
};

struct pmc_reg_config {
	u8 mckr;
};

struct ddrc_reg_config {
	u32 type_offset;
	u32 type_mask;
};

struct reg_config {
	struct shdwc_reg_config shdwc;
	struct pmc_reg_config pmc;
	struct ddrc_reg_config ddrc;
};

struct shdwc {
	const struct reg_config *rcfg;
	struct clk *sclk;
	void __iomem *shdwc_base;
	void __iomem *mpddrc_base;
	void __iomem *pmc_base;
};

/*
 * Hold configuration here, cannot be more than one instance of the driver
 * since pm_power_off itself is global.
 */
static struct shdwc *at91_shdwc;

static const unsigned long long sdwc_dbc_period[] = {
	0, 3, 32, 512, 4096, 32768,
};

static void at91_wakeup_status(struct platform_device *pdev)
{
	struct shdwc *shdw = platform_get_drvdata(pdev);
	const struct reg_config *rcfg = shdw->rcfg;
	u32 reg;
	char *reason = "unknown";

	reg = readl(shdw->shdwc_base + AT91_SHDW_SR);

	dev_dbg(&pdev->dev, "%s: status = %#x\n", __func__, reg);

	/* Simple power-on, just bail out */
	if (!reg)
		return;

	if (SHDW_WK_PIN(reg, &rcfg->shdwc))
		reason = "WKUP pin";
	else if (SHDW_RTCWK(reg, &rcfg->shdwc))
		reason = "RTC";
	else if (SHDW_RTTWK(reg, &rcfg->shdwc))
		reason = "RTT";

	dev_info(&pdev->dev, "Wake-Up source: %s\n", reason);
}

static void at91_poweroff(void)
{
	asm volatile(
		/* Align to cache lines */
		".balign 32\n\t"

		/* Ensure AT91_SHDW_CR is in the TLB by reading it */
		"	ldr	r6, [%2, #" __stringify(AT91_SHDW_CR) "]\n\t"

		/* Power down SDRAM0 */
		"	tst	%0, #0\n\t"
		"	beq	1f\n\t"
		"	str	%1, [%0, #" __stringify(AT91_DDRSDRC_LPR) "]\n\t"

		/* Switch the master clock source to slow clock. */
		"1:	ldr	r6, [%4, %5]\n\t"
		"	bic	r6, r6,  #" __stringify(AT91_PMC_CSS) "\n\t"
		"	str	r6, [%4, %5]\n\t"
		/* Wait for clock switch. */
		"2:	ldr	r6, [%4, #" __stringify(AT91_PMC_SR) "]\n\t"
		"	tst	r6, #"	    __stringify(AT91_PMC_MCKRDY) "\n\t"
		"	beq	2b\n\t"

		/* Shutdown CPU */

Annotation

Implementation Notes