root/drivers/cpufreq/sc520_freq.c

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

DEFINITIONS

This source file includes following definitions.
  1. sc520_freq_get_cpu_frequency
  2. sc520_freq_target
  3. sc520_freq_cpu_init
  4. sc520_freq_init
  5. sc520_freq_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      sc520_freq.c: cpufreq driver for the AMD Elan sc520
   4  *
   5  *      Copyright (C) 2005 Sean Young <sean@mess.org>
   6  *
   7  *      Based on elanfreq.c
   8  *
   9  *      2005-03-30: - initial revision
  10  */
  11 
  12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13 
  14 #include <linux/kernel.h>
  15 #include <linux/module.h>
  16 #include <linux/init.h>
  17 
  18 #include <linux/delay.h>
  19 #include <linux/cpufreq.h>
  20 #include <linux/timex.h>
  21 #include <linux/io.h>
  22 
  23 #include <asm/cpu_device_id.h>
  24 #include <asm/msr.h>
  25 
  26 #define MMCR_BASE       0xfffef000      /* The default base address */
  27 #define OFFS_CPUCTL     0x2   /* CPU Control Register */
  28 
  29 static __u8 __iomem *cpuctl;
  30 
  31 static struct cpufreq_frequency_table sc520_freq_table[] = {
  32         {0, 0x01,       100000},
  33         {0, 0x02,       133000},
  34         {0, 0,  CPUFREQ_TABLE_END},
  35 };
  36 
  37 static unsigned int sc520_freq_get_cpu_frequency(unsigned int cpu)
  38 {
  39         u8 clockspeed_reg = *cpuctl;
  40 
  41         switch (clockspeed_reg & 0x03) {
  42         default:
  43                 pr_err("error: cpuctl register has unexpected value %02x\n",
  44                        clockspeed_reg);
  45         case 0x01:
  46                 return 100000;
  47         case 0x02:
  48                 return 133000;
  49         }
  50 }
  51 
  52 static int sc520_freq_target(struct cpufreq_policy *policy, unsigned int state)
  53 {
  54 
  55         u8 clockspeed_reg;
  56 
  57         local_irq_disable();
  58 
  59         clockspeed_reg = *cpuctl & ~0x03;
  60         *cpuctl = clockspeed_reg | sc520_freq_table[state].driver_data;
  61 
  62         local_irq_enable();
  63 
  64         return 0;
  65 }
  66 
  67 /*
  68  *      Module init and exit code
  69  */
  70 
  71 static int sc520_freq_cpu_init(struct cpufreq_policy *policy)
  72 {
  73         struct cpuinfo_x86 *c = &cpu_data(0);
  74 
  75         /* capability check */
  76         if (c->x86_vendor != X86_VENDOR_AMD ||
  77             c->x86 != 4 || c->x86_model != 9)
  78                 return -ENODEV;
  79 
  80         /* cpuinfo and default policy values */
  81         policy->cpuinfo.transition_latency = 1000000; /* 1ms */
  82         policy->freq_table = sc520_freq_table;
  83 
  84         return 0;
  85 }
  86 
  87 
  88 static struct cpufreq_driver sc520_freq_driver = {
  89         .get    = sc520_freq_get_cpu_frequency,
  90         .verify = cpufreq_generic_frequency_table_verify,
  91         .target_index = sc520_freq_target,
  92         .init   = sc520_freq_cpu_init,
  93         .name   = "sc520_freq",
  94         .attr   = cpufreq_generic_attr,
  95 };
  96 
  97 static const struct x86_cpu_id sc520_ids[] = {
  98         { X86_VENDOR_AMD, 4, 9 },
  99         {}
 100 };
 101 MODULE_DEVICE_TABLE(x86cpu, sc520_ids);
 102 
 103 static int __init sc520_freq_init(void)
 104 {
 105         int err;
 106 
 107         if (!x86_match_cpu(sc520_ids))
 108                 return -ENODEV;
 109 
 110         cpuctl = ioremap((unsigned long)(MMCR_BASE + OFFS_CPUCTL), 1);
 111         if (!cpuctl) {
 112                 pr_err("sc520_freq: error: failed to remap memory\n");
 113                 return -ENOMEM;
 114         }
 115 
 116         err = cpufreq_register_driver(&sc520_freq_driver);
 117         if (err)
 118                 iounmap(cpuctl);
 119 
 120         return err;
 121 }
 122 
 123 
 124 static void __exit sc520_freq_exit(void)
 125 {
 126         cpufreq_unregister_driver(&sc520_freq_driver);
 127         iounmap(cpuctl);
 128 }
 129 
 130 
 131 MODULE_LICENSE("GPL");
 132 MODULE_AUTHOR("Sean Young <sean@mess.org>");
 133 MODULE_DESCRIPTION("cpufreq driver for AMD's Elan sc520 CPU");
 134 
 135 module_init(sc520_freq_init);
 136 module_exit(sc520_freq_exit);
 137 

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