~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc/kernel/apc.c

Version: ~ [ linux-5.8-rc5 ] ~ [ linux-5.7.8 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.51 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.132 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.188 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.230 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.230 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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);
197 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp