cregit-Linux how code gets into the kernel

Release 4.11 arch/avr32/mach-at32ap/pm.c

/*
 * AVR32 AP Power Management
 *
 * Copyright (C) 2008 Atmel Corporation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 */
#include <linux/io.h>
#include <linux/suspend.h>
#include <linux/vmalloc.h>

#include <asm/cacheflush.h>
#include <asm/sysreg.h>

#include <mach/chip.h>
#include <mach/pm.h>
#include <mach/sram.h>

#include "sdramc.h"


#define SRAM_PAGE_FLAGS	(SYSREG_BIT(TLBELO_D) | SYSREG_BF(SZ, 1)        \
                                | SYSREG_BF(AP, 3) | SYSREG_BIT(G))



static unsigned long	pm_sram_start;

static size_t		pm_sram_size;

static struct vm_struct	*pm_sram_area;


static void (*avr32_pm_enter_standby)(unsigned long sdramc_base);

static void (*avr32_pm_enter_str)(unsigned long sdramc_base);

/*
 * Must be called with interrupts disabled. Exceptions will be masked
 * on return (i.e. all exceptions will be "unrecoverable".)
 */

static void *avr32_pm_map_sram(void) { unsigned long vaddr; unsigned long page_addr; u32 tlbehi; u32 mmucr; vaddr = (unsigned long)pm_sram_area->addr; page_addr = pm_sram_start & PAGE_MASK; /* * Mask exceptions and grab the first TLB entry. We won't be * needing it while sleeping. */ asm volatile("ssrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory"); mmucr = sysreg_read(MMUCR); tlbehi = sysreg_read(TLBEHI); sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr)); tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); tlbehi |= vaddr & PAGE_MASK; tlbehi |= SYSREG_BIT(TLBEHI_V); sysreg_write(TLBELO, page_addr | SRAM_PAGE_FLAGS); sysreg_write(TLBEHI, tlbehi); __builtin_tlbw(); return (void *)(vaddr + pm_sram_start - page_addr); }

Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen130100.00%1100.00%
Total130100.00%1100.00%

/* * Must be called with interrupts disabled. Exceptions will be * unmasked on return. */
static void avr32_pm_unmap_sram(void) { u32 mmucr; u32 tlbehi; u32 tlbarlo; /* Going to update TLB entry at index 0 */ mmucr = sysreg_read(MMUCR); tlbehi = sysreg_read(TLBEHI); sysreg_write(MMUCR, SYSREG_BFINS(DRP, 0, mmucr)); /* Clear the "valid" bit */ tlbehi = SYSREG_BF(ASID, SYSREG_BFEXT(ASID, tlbehi)); sysreg_write(TLBEHI, tlbehi); /* Mark it as "not accessed" */ tlbarlo = sysreg_read(TLBARLO); sysreg_write(TLBARLO, tlbarlo | 0x80000000U); /* Update the TLB */ __builtin_tlbw(); /* Unmask exceptions */ asm volatile("csrf %0" : : "i"(SYSREG_EM_OFFSET) : "memory"); }

Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen93100.00%1100.00%
Total93100.00%1100.00%


static int avr32_pm_valid_state(suspend_state_t state) { switch (state) { case PM_SUSPEND_ON: case PM_SUSPEND_STANDBY: case PM_SUSPEND_MEM: return 1; default: return 0; } }

Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen31100.00%1100.00%
Total31100.00%1100.00%


static int avr32_pm_enter(suspend_state_t state) { u32 lpr_saved; u32 evba_saved; void *sram; switch (state) { case PM_SUSPEND_STANDBY: sram = avr32_pm_map_sram(); /* Switch to in-sram exception handlers */ evba_saved = sysreg_read(EVBA); sysreg_write(EVBA, (unsigned long)sram); /* * Save the LPR register so that we can re-enable * SDRAM Low Power mode on resume. */ lpr_saved = sdramc_readl(LPR); pr_debug("%s: Entering standby...\n", __func__); avr32_pm_enter_standby(SDRAMC_BASE); sdramc_writel(LPR, lpr_saved); /* Switch back to regular exception handlers */ sysreg_write(EVBA, evba_saved); avr32_pm_unmap_sram(); break; case PM_SUSPEND_MEM: sram = avr32_pm_map_sram(); /* Switch to in-sram exception handlers */ evba_saved = sysreg_read(EVBA); sysreg_write(EVBA, (unsigned long)sram); /* * Save the LPR register so that we can re-enable * SDRAM Low Power mode on resume. */ lpr_saved = sdramc_readl(LPR); pr_debug("%s: Entering suspend-to-ram...\n", __func__); avr32_pm_enter_str(SDRAMC_BASE); sdramc_writel(LPR, lpr_saved); /* Switch back to regular exception handlers */ sysreg_write(EVBA, evba_saved); avr32_pm_unmap_sram(); break; case PM_SUSPEND_ON: pr_debug("%s: Entering idle...\n", __func__); cpu_enter_idle(); break; default: pr_debug("%s: Invalid suspend state %d\n", __func__, state); goto out; } pr_debug("%s: wakeup\n", __func__); out: return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen196100.00%1100.00%
Total196100.00%1100.00%

static const struct platform_suspend_ops avr32_pm_ops = { .valid = avr32_pm_valid_state, .enter = avr32_pm_enter, };
static unsigned long __init avr32_pm_offset(void *symbol) { extern u8 pm_exception[]; return (unsigned long)symbol - (unsigned long)pm_exception; }

Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen2996.67%150.00%
Matthias Brugger13.33%150.00%
Total30100.00%2100.00%


static int __init avr32_pm_init(void) { extern u8 pm_exception[]; extern u8 pm_irq0[]; extern u8 pm_standby[]; extern u8 pm_suspend_to_ram[]; extern u8 pm_sram_end[]; void *dst; /* * To keep things simple, we depend on not needing more than a * single page. */ pm_sram_size = avr32_pm_offset(pm_sram_end); if (pm_sram_size > PAGE_SIZE) goto err; pm_sram_start = sram_alloc(pm_sram_size); if (!pm_sram_start) goto err_alloc_sram; /* Grab a virtual area we can use later on. */ pm_sram_area = get_vm_area(pm_sram_size, VM_IOREMAP); if (!pm_sram_area) goto err_vm_area; pm_sram_area->phys_addr = pm_sram_start; local_irq_disable(); dst = avr32_pm_map_sram(); memcpy(dst, pm_exception, pm_sram_size); flush_dcache_region(dst, pm_sram_size); invalidate_icache_region(dst, pm_sram_size); avr32_pm_unmap_sram(); local_irq_enable(); avr32_pm_enter_standby = dst + avr32_pm_offset(pm_standby); avr32_pm_enter_str = dst + avr32_pm_offset(pm_suspend_to_ram); intc_set_suspend_handler(avr32_pm_offset(pm_irq0)); suspend_set_ops(&avr32_pm_ops); printk("AVR32 AP Power Management enabled\n"); return 0; err_vm_area: sram_free(pm_sram_start, pm_sram_size); err_alloc_sram: err: pr_err("AVR32 Power Management initialization failed\n"); return -ENOMEM; }

Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen193100.00%1100.00%
Total193100.00%1100.00%

arch_initcall(avr32_pm_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
Håvard Skinnemoen76799.74%360.00%
Lionel Debroux10.13%120.00%
Matthias Brugger10.13%120.00%
Total769100.00%5100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.