arch/arm/mach-davinci/pm.c

Source file repositories/reference/linux-study-clean/arch/arm/mach-davinci/pm.c

File Facts

System
Linux kernel
Corpus path
arch/arm/mach-davinci/pm.c
Extension
.c
Size
4137 bytes
Lines
171
Domain
Architecture Layer
Bucket
arch/arm
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/*
 * DaVinci Power Management Routines
 *
 * Copyright (C) 2009 Texas Instruments, Inc. https://www.ti.com/
 */

#include <linux/pm.h>
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/spinlock.h>

#include <asm/cacheflush.h>
#include <asm/delay.h>
#include <asm/io.h>

#include "common.h"
#include "da8xx.h"
#include "mux.h"
#include "pm.h"
#include "clock.h"
#include "psc.h"
#include "sram.h"

#define DA850_PLL1_BASE		0x01e1a000
#define DEEPSLEEP_SLEEPCOUNT_MASK	0xFFFF
#define DEEPSLEEP_SLEEPCOUNT		128

static void (*davinci_sram_suspend) (struct davinci_pm_config *);
static struct davinci_pm_config pm_config = {
	.sleepcount = DEEPSLEEP_SLEEPCOUNT,
	.ddrpsc_num = DA8XX_LPSC1_EMIF3C,
};

static void davinci_sram_push(void *dest, void *src, unsigned int size)
{
	memcpy(dest, src, size);
	flush_icache_range((unsigned long)dest, (unsigned long)(dest + size));
}

static void davinci_pm_suspend(void)
{
	unsigned val;

	if (pm_config.cpupll_reg_base != pm_config.ddrpll_reg_base) {

		/* Switch CPU PLL to bypass mode */
		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
		val &= ~(PLLCTL_PLLENSRC | PLLCTL_PLLEN);
		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);

		udelay(PLL_BYPASS_TIME);

		/* Powerdown CPU PLL */
		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
		val |= PLLCTL_PLLPWRDN;
		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);
	}

	/* Configure sleep count in deep sleep register */
	val = __raw_readl(pm_config.deepsleep_reg);
	val &= ~DEEPSLEEP_SLEEPCOUNT_MASK;
	val |= pm_config.sleepcount;
	__raw_writel(val, pm_config.deepsleep_reg);

	/* System goes to sleep in this call */
	davinci_sram_suspend(&pm_config);

	if (pm_config.cpupll_reg_base != pm_config.ddrpll_reg_base) {

		/* put CPU PLL in reset */
		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
		val &= ~PLLCTL_PLLRST;
		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);

		/* put CPU PLL in power down */
		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
		val &= ~PLLCTL_PLLPWRDN;
		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);

		/* wait for CPU PLL reset */
		udelay(PLL_RESET_TIME);

		/* bring CPU PLL out of reset */
		val = __raw_readl(pm_config.cpupll_reg_base + PLLCTL);
		val |= PLLCTL_PLLRST;
		__raw_writel(val, pm_config.cpupll_reg_base + PLLCTL);

Annotation

Implementation Notes