root/arch/sparc/kernel/apc.c

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

DEFINITIONS

This source file includes following definitions.
  1. apc_setup
  2. apc_swift_idle
  3. apc_free
  4. apc_open
  5. apc_release
  6. apc_ioctl
  7. apc_probe
  8. apc_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* apc - Driver implementation for power management functions
   3  * of Aurora Personality Chip (APC) on SPARCstation-4/5 and
   4  * derivatives.
   5  *
   6  * Copyright (c) 2002 Eric Brower (ebrower@usa.net)
   7  */
   8 
   9 #include <linux/kernel.h>
  10 #include <linux/fs.h>
  11 #include <linux/errno.h>
  12 #include <linux/init.h>
  13 #include <linux/miscdevice.h>
  14 #include <linux/pm.h>
  15 #include <linux/of.h>
  16 #include <linux/of_device.h>
  17 #include <linux/module.h>
  18 
  19 #include <asm/io.h>
  20 #include <asm/oplib.h>
  21 #include <linux/uaccess.h>
  22 #include <asm/auxio.h>
  23 #include <asm/apc.h>
  24 #include <asm/processor.h>
  25 
  26 /* Debugging
  27  * 
  28  * #define APC_DEBUG_LED
  29  */
  30 
  31 #define APC_MINOR       MISC_DYNAMIC_MINOR
  32 #define APC_OBPNAME     "power-management"
  33 #define APC_DEVNAME "apc"
  34 
  35 static u8 __iomem *regs;
  36 static int apc_no_idle = 0;
  37 
  38 #define apc_readb(offs)         (sbus_readb(regs+offs))
  39 #define apc_writeb(val, offs)   (sbus_writeb(val, regs+offs))
  40 
  41 /* Specify "apc=noidle" on the kernel command line to 
  42  * disable APC CPU standby support.  Certain prototype
  43  * systems (SPARCstation-Fox) do not play well with APC
  44  * CPU idle, so disable this if your system has APC and 
  45  * crashes randomly.
  46  */
  47 static int __init apc_setup(char *str) 
  48 {
  49         if(!strncmp(str, "noidle", strlen("noidle"))) {
  50                 apc_no_idle = 1;
  51                 return 1;
  52         }
  53         return 0;
  54 }
  55 __setup("apc=", apc_setup);
  56 
  57 /* 
  58  * CPU idle callback function
  59  * See .../arch/sparc/kernel/process.c
  60  */
  61 static void apc_swift_idle(void)
  62 {
  63 #ifdef APC_DEBUG_LED
  64         set_auxio(0x00, AUXIO_LED); 
  65 #endif
  66 
  67         apc_writeb(apc_readb(APC_IDLE_REG) | APC_IDLE_ON, APC_IDLE_REG);
  68 
  69 #ifdef APC_DEBUG_LED
  70         set_auxio(AUXIO_LED, 0x00); 
  71 #endif
  72 } 
  73 
  74 static inline void apc_free(struct platform_device *op)
  75 {
  76         of_iounmap(&op->resource[0], regs, resource_size(&op->resource[0]));
  77 }
  78 
  79 static int apc_open(struct inode *inode, struct file *f)
  80 {
  81         return 0;
  82 }
  83 
  84 static int apc_release(struct inode *inode, struct file *f)
  85 {
  86         return 0;
  87 }
  88 
  89 static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
  90 {
  91         __u8 inarg, __user *arg = (__u8 __user *) __arg;
  92 
  93         switch (cmd) {
  94         case APCIOCGFANCTL:
  95                 if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg))
  96                         return -EFAULT;
  97                 break;
  98 
  99         case APCIOCGCPWR:
 100                 if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg))
 101                         return -EFAULT;
 102                 break;
 103 
 104         case APCIOCGBPORT:
 105                 if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg))
 106                         return -EFAULT;
 107                 break;
 108 
 109         case APCIOCSFANCTL:
 110                 if (get_user(inarg, arg))
 111                         return -EFAULT;
 112                 apc_writeb(inarg & APC_REGMASK, APC_FANCTL_REG);
 113                 break;
 114 
 115         case APCIOCSCPWR:
 116                 if (get_user(inarg, arg))
 117                         return -EFAULT;
 118                 apc_writeb(inarg & APC_REGMASK, APC_CPOWER_REG);
 119                 break;
 120 
 121         case APCIOCSBPORT:
 122                 if (get_user(inarg, arg))
 123                         return -EFAULT;
 124                 apc_writeb(inarg & APC_BPMASK, APC_BPORT_REG);
 125                 break;
 126 
 127         default:
 128                 return -EINVAL;
 129         }
 130 
 131         return 0;
 132 }
 133 
 134 static const struct file_operations apc_fops = {
 135         .unlocked_ioctl =       apc_ioctl,
 136         .open =                 apc_open,
 137         .release =              apc_release,
 138         .llseek =               noop_llseek,
 139 };
 140 
 141 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
 142 
 143 static int apc_probe(struct platform_device *op)
 144 {
 145         int err;
 146 
 147         regs = of_ioremap(&op->resource[0], 0,
 148                           resource_size(&op->resource[0]), APC_OBPNAME);
 149         if (!regs) {
 150                 printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME);
 151                 return -ENODEV;
 152         }
 153 
 154         err = misc_register(&apc_miscdev);
 155         if (err) {
 156                 printk(KERN_ERR "%s: unable to register device\n", APC_DEVNAME);
 157                 apc_free(op);
 158                 return -ENODEV;
 159         }
 160 
 161         /* Assign power management IDLE handler */
 162         if (!apc_no_idle)
 163                 sparc_idle = apc_swift_idle;
 164 
 165         printk(KERN_INFO "%s: power management initialized%s\n", 
 166                APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : "");
 167 
 168         return 0;
 169 }
 170 
 171 static const struct of_device_id apc_match[] = {
 172         {
 173                 .name = APC_OBPNAME,
 174         },
 175         {},
 176 };
 177 MODULE_DEVICE_TABLE(of, apc_match);
 178 
 179 static struct platform_driver apc_driver = {
 180         .driver = {
 181                 .name = "apc",
 182                 .of_match_table = apc_match,
 183         },
 184         .probe          = apc_probe,
 185 };
 186 
 187 static int __init apc_init(void)
 188 {
 189         return platform_driver_register(&apc_driver);
 190 }
 191 
 192 /* This driver is not critical to the boot process
 193  * and is easiest to ioremap when SBus is already
 194  * initialized, so we install ourselves thusly:
 195  */
 196 __initcall(apc_init);

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