root/arch/sparc/kernel/leon_pmc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pmc_leon_need_fixup
  2. pmc_leon_idle_fixup
  3. pmc_leon_idle
  4. leon_pmc_install

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* leon_pmc.c: LEON Power-down cpu_idle() handler
   3  *
   4  * Copyright (C) 2011 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
   5  */
   6 
   7 #include <linux/init.h>
   8 #include <linux/pm.h>
   9 
  10 #include <asm/leon_amba.h>
  11 #include <asm/cpu_type.h>
  12 #include <asm/leon.h>
  13 #include <asm/processor.h>
  14 
  15 /* List of Systems that need fixup instructions around power-down instruction */
  16 static unsigned int pmc_leon_fixup_ids[] = {
  17         AEROFLEX_UT699,
  18         GAISLER_GR712RC,
  19         LEON4_NEXTREME1,
  20         0
  21 };
  22 
  23 static int pmc_leon_need_fixup(void)
  24 {
  25         unsigned int systemid = amba_system_id >> 16;
  26         unsigned int *id;
  27 
  28         id = &pmc_leon_fixup_ids[0];
  29         while (*id != 0) {
  30                 if (*id == systemid)
  31                         return 1;
  32                 id++;
  33         }
  34 
  35         return 0;
  36 }
  37 
  38 /*
  39  * CPU idle callback function for systems that need some extra handling
  40  * See .../arch/sparc/kernel/process.c
  41  */
  42 static void pmc_leon_idle_fixup(void)
  43 {
  44         /* Prepare an address to a non-cachable region. APB is always
  45          * none-cachable. One instruction is executed after the Sleep
  46          * instruction, we make sure to read the bus and throw away the
  47          * value by accessing a non-cachable area, also we make sure the
  48          * MMU does not get a TLB miss here by using the MMU BYPASS ASI.
  49          */
  50         register unsigned int address = (unsigned int)leon3_irqctrl_regs;
  51 
  52         /* Interrupts need to be enabled to not hang the CPU */
  53         local_irq_enable();
  54 
  55         __asm__ __volatile__ (
  56                 "wr     %%g0, %%asr19\n"
  57                 "lda    [%0] %1, %%g0\n"
  58                 :
  59                 : "r"(address), "i"(ASI_LEON_BYPASS));
  60 }
  61 
  62 /*
  63  * CPU idle callback function
  64  * See .../arch/sparc/kernel/process.c
  65  */
  66 static void pmc_leon_idle(void)
  67 {
  68         /* Interrupts need to be enabled to not hang the CPU */
  69         local_irq_enable();
  70 
  71         /* For systems without power-down, this will be no-op */
  72         __asm__ __volatile__ ("wr       %g0, %asr19\n\t");
  73 }
  74 
  75 /* Install LEON Power Down function */
  76 static int __init leon_pmc_install(void)
  77 {
  78         if (sparc_cpu_model == sparc_leon) {
  79                 /* Assign power management IDLE handler */
  80                 if (pmc_leon_need_fixup())
  81                         sparc_idle = pmc_leon_idle_fixup;
  82                 else
  83                         sparc_idle = pmc_leon_idle;
  84 
  85                 printk(KERN_INFO "leon: power management initialized\n");
  86         }
  87 
  88         return 0;
  89 }
  90 
  91 /* This driver is not critical to the boot process, don't care
  92  * if initialized late.
  93  */
  94 late_initcall(leon_pmc_install);

/* [<][>][^][v][top][bottom][index][help] */