mirror of
https://github.com/torvalds/linux.git
synced 2024-11-28 23:21:31 +00:00
263291fa44
The DT of_device.h and of_platform.h date back to the separate of_platform_bus_type before it was merged into the regular platform bus. As part of that merge prepping Arm DT support 13 years ago, they "temporarily" include each other. They also include platform_device.h and of.h. As a result, there's a pretty much random mix of those include files used throughout the tree. In order to detangle these headers and replace the implicit includes with struct declarations, users need to explicitly include the correct includes. Acked-by: Sam Ravnborg <sam@ravnborg.org> Link: https://lore.kernel.org/all/20230718143211.1066810-1-robh@kernel.org/ Signed-off-by: Rob Herring <robh@kernel.org>
197 lines
4.1 KiB
C
197 lines
4.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* apc - Driver implementation for power management functions
|
|
* of Aurora Personality Chip (APC) on SPARCstation-4/5 and
|
|
* derivatives.
|
|
*
|
|
* Copyright (c) 2002 Eric Brower (ebrower@usa.net)
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/init.h>
|
|
#include <linux/miscdevice.h>
|
|
#include <linux/pm.h>
|
|
#include <linux/of.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/module.h>
|
|
|
|
#include <asm/io.h>
|
|
#include <asm/oplib.h>
|
|
#include <linux/uaccess.h>
|
|
#include <asm/auxio.h>
|
|
#include <asm/apc.h>
|
|
#include <asm/processor.h>
|
|
|
|
/* Debugging
|
|
*
|
|
* #define APC_DEBUG_LED
|
|
*/
|
|
|
|
#define APC_MINOR MISC_DYNAMIC_MINOR
|
|
#define APC_OBPNAME "power-management"
|
|
#define APC_DEVNAME "apc"
|
|
|
|
static u8 __iomem *regs;
|
|
static int apc_no_idle = 0;
|
|
|
|
#define apc_readb(offs) (sbus_readb(regs+offs))
|
|
#define apc_writeb(val, offs) (sbus_writeb(val, regs+offs))
|
|
|
|
/* Specify "apc=noidle" on the kernel command line to
|
|
* disable APC CPU standby support. Certain prototype
|
|
* systems (SPARCstation-Fox) do not play well with APC
|
|
* CPU idle, so disable this if your system has APC and
|
|
* crashes randomly.
|
|
*/
|
|
static int __init apc_setup(char *str)
|
|
{
|
|
if(!strncmp(str, "noidle", strlen("noidle"))) {
|
|
apc_no_idle = 1;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
__setup("apc=", apc_setup);
|
|
|
|
/*
|
|
* CPU idle callback function
|
|
* See .../arch/sparc/kernel/process.c
|
|
*/
|
|
static void apc_swift_idle(void)
|
|
{
|
|
#ifdef APC_DEBUG_LED
|
|
set_auxio(0x00, AUXIO_LED);
|
|
#endif
|
|
|
|
apc_writeb(apc_readb(APC_IDLE_REG) | APC_IDLE_ON, APC_IDLE_REG);
|
|
|
|
#ifdef APC_DEBUG_LED
|
|
set_auxio(AUXIO_LED, 0x00);
|
|
#endif
|
|
}
|
|
|
|
static inline void apc_free(struct platform_device *op)
|
|
{
|
|
of_iounmap(&op->resource[0], regs, resource_size(&op->resource[0]));
|
|
}
|
|
|
|
static int apc_open(struct inode *inode, struct file *f)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static int apc_release(struct inode *inode, struct file *f)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static long apc_ioctl(struct file *f, unsigned int cmd, unsigned long __arg)
|
|
{
|
|
__u8 inarg, __user *arg = (__u8 __user *) __arg;
|
|
|
|
switch (cmd) {
|
|
case APCIOCGFANCTL:
|
|
if (put_user(apc_readb(APC_FANCTL_REG) & APC_REGMASK, arg))
|
|
return -EFAULT;
|
|
break;
|
|
|
|
case APCIOCGCPWR:
|
|
if (put_user(apc_readb(APC_CPOWER_REG) & APC_REGMASK, arg))
|
|
return -EFAULT;
|
|
break;
|
|
|
|
case APCIOCGBPORT:
|
|
if (put_user(apc_readb(APC_BPORT_REG) & APC_BPMASK, arg))
|
|
return -EFAULT;
|
|
break;
|
|
|
|
case APCIOCSFANCTL:
|
|
if (get_user(inarg, arg))
|
|
return -EFAULT;
|
|
apc_writeb(inarg & APC_REGMASK, APC_FANCTL_REG);
|
|
break;
|
|
|
|
case APCIOCSCPWR:
|
|
if (get_user(inarg, arg))
|
|
return -EFAULT;
|
|
apc_writeb(inarg & APC_REGMASK, APC_CPOWER_REG);
|
|
break;
|
|
|
|
case APCIOCSBPORT:
|
|
if (get_user(inarg, arg))
|
|
return -EFAULT;
|
|
apc_writeb(inarg & APC_BPMASK, APC_BPORT_REG);
|
|
break;
|
|
|
|
default:
|
|
return -EINVAL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct file_operations apc_fops = {
|
|
.unlocked_ioctl = apc_ioctl,
|
|
.open = apc_open,
|
|
.release = apc_release,
|
|
.llseek = noop_llseek,
|
|
};
|
|
|
|
static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
|
|
|
|
static int apc_probe(struct platform_device *op)
|
|
{
|
|
int err;
|
|
|
|
regs = of_ioremap(&op->resource[0], 0,
|
|
resource_size(&op->resource[0]), APC_OBPNAME);
|
|
if (!regs) {
|
|
printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME);
|
|
return -ENODEV;
|
|
}
|
|
|
|
err = misc_register(&apc_miscdev);
|
|
if (err) {
|
|
printk(KERN_ERR "%s: unable to register device\n", APC_DEVNAME);
|
|
apc_free(op);
|
|
return -ENODEV;
|
|
}
|
|
|
|
/* Assign power management IDLE handler */
|
|
if (!apc_no_idle)
|
|
sparc_idle = apc_swift_idle;
|
|
|
|
printk(KERN_INFO "%s: power management initialized%s\n",
|
|
APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : "");
|
|
|
|
return 0;
|
|
}
|
|
|
|
static const struct of_device_id apc_match[] = {
|
|
{
|
|
.name = APC_OBPNAME,
|
|
},
|
|
{},
|
|
};
|
|
MODULE_DEVICE_TABLE(of, apc_match);
|
|
|
|
static struct platform_driver apc_driver = {
|
|
.driver = {
|
|
.name = "apc",
|
|
.of_match_table = apc_match,
|
|
},
|
|
.probe = apc_probe,
|
|
};
|
|
|
|
static int __init apc_init(void)
|
|
{
|
|
return platform_driver_register(&apc_driver);
|
|
}
|
|
|
|
/* This driver is not critical to the boot process
|
|
* and is easiest to ioremap when SBus is already
|
|
* initialized, so we install ourselves thusly:
|
|
*/
|
|
__initcall(apc_init);
|