arch/arm/mach-mvebu/pm.c

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

File Facts

System
Linux kernel
Corpus path
arch/arm/mach-mvebu/pm.c
Extension
.c
Size
6299 bytes
Lines
268
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
/*
 * Suspend/resume support. Currently supporting Armada XP only.
 *
 * Copyright (C) 2014 Marvell
 *
 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
 */

#include <linux/cpu_pm.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mbus.h>
#include <linux/of_address.h>
#include <linux/suspend.h>
#include <asm/cacheflush.h>
#include <asm/outercache.h>
#include <asm/suspend.h>

#include "coherency.h"
#include "common.h"
#include "pmsu.h"

#define SDRAM_CONFIG_OFFS                  0x0
#define  SDRAM_CONFIG_SR_MODE_BIT          BIT(24)
#define SDRAM_OPERATION_OFFS               0x18
#define  SDRAM_OPERATION_SELF_REFRESH      0x7
#define SDRAM_DLB_EVICTION_OFFS            0x30c
#define  SDRAM_DLB_EVICTION_THRESHOLD_MASK 0xff

static void (*mvebu_board_pm_enter)(void __iomem *sdram_reg, u32 srcmd);
static void __iomem *sdram_ctrl;

static int mvebu_pm_powerdown(unsigned long data)
{
	u32 reg, srcmd;

	flush_cache_all();
	outer_flush_all();

	/*
	 * Issue a Data Synchronization Barrier instruction to ensure
	 * that all state saving has been completed.
	 */
	dsb();

	/* Flush the DLB and wait ~7 usec */
	reg = readl(sdram_ctrl + SDRAM_DLB_EVICTION_OFFS);
	reg &= ~SDRAM_DLB_EVICTION_THRESHOLD_MASK;
	writel(reg, sdram_ctrl + SDRAM_DLB_EVICTION_OFFS);

	udelay(7);

	/* Set DRAM in battery backup mode */
	reg = readl(sdram_ctrl + SDRAM_CONFIG_OFFS);
	reg &= ~SDRAM_CONFIG_SR_MODE_BIT;
	writel(reg, sdram_ctrl + SDRAM_CONFIG_OFFS);

	/* Prepare to go to self-refresh */

	srcmd = readl(sdram_ctrl + SDRAM_OPERATION_OFFS);
	srcmd &= ~0x1F;
	srcmd |= SDRAM_OPERATION_SELF_REFRESH;

	mvebu_board_pm_enter(sdram_ctrl + SDRAM_OPERATION_OFFS, srcmd);

	return 0;
}

#define BOOT_INFO_ADDR      0x3000
#define BOOT_MAGIC_WORD	    0xdeadb002
#define BOOT_MAGIC_LIST_END 0xffffffff

/*
 * Those registers are accessed before switching the internal register
 * base, which is why we hardcode the 0xd0000000 base address, the one
 * used by the SoC out of reset.
 */
#define MBUS_WINDOW_12_CTRL       0xd00200b0
#define MBUS_INTERNAL_REG_ADDRESS 0xd0020080

#define SDRAM_WIN_BASE_REG(x)	(0x20180 + (0x8*x))
#define SDRAM_WIN_CTRL_REG(x)	(0x20184 + (0x8*x))

static phys_addr_t mvebu_internal_reg_base(void)
{
	struct device_node *np;
	__be32 in_addr[2];

Annotation

Implementation Notes