Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/platform/iris/iris.c
26481 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Eurobraille/Iris power off support.
4
*
5
* Eurobraille's Iris machine is a PC with no APM or ACPI support.
6
* It is shutdown by a special I/O sequence which this module provides.
7
*
8
* Copyright (C) Shérab <[email protected]>
9
*/
10
11
#include <linux/moduleparam.h>
12
#include <linux/module.h>
13
#include <linux/platform_device.h>
14
#include <linux/kernel.h>
15
#include <linux/errno.h>
16
#include <linux/delay.h>
17
#include <linux/pm.h>
18
#include <asm/io.h>
19
20
#define IRIS_GIO_BASE 0x340
21
#define IRIS_GIO_INPUT IRIS_GIO_BASE
22
#define IRIS_GIO_OUTPUT (IRIS_GIO_BASE + 1)
23
#define IRIS_GIO_PULSE 0x80 /* First byte to send */
24
#define IRIS_GIO_REST 0x00 /* Second byte to send */
25
#define IRIS_GIO_NODEV 0xff /* Likely not an Iris */
26
27
MODULE_LICENSE("GPL");
28
MODULE_AUTHOR("Sébastien Hinderer <[email protected]>");
29
MODULE_DESCRIPTION("A power_off handler for Iris devices from EuroBraille");
30
31
static bool force;
32
33
module_param(force, bool, 0);
34
MODULE_PARM_DESC(force, "Set to one to force poweroff handler installation.");
35
36
static void (*old_pm_power_off)(void);
37
38
static void iris_power_off(void)
39
{
40
outb(IRIS_GIO_PULSE, IRIS_GIO_OUTPUT);
41
msleep(850);
42
outb(IRIS_GIO_REST, IRIS_GIO_OUTPUT);
43
}
44
45
/*
46
* Before installing the power_off handler, try to make sure the OS is
47
* running on an Iris. Since Iris does not support DMI, this is done
48
* by reading its input port and seeing whether the read value is
49
* meaningful.
50
*/
51
static int iris_probe(struct platform_device *pdev)
52
{
53
unsigned char status = inb(IRIS_GIO_INPUT);
54
if (status == IRIS_GIO_NODEV) {
55
printk(KERN_ERR "This machine does not seem to be an Iris. "
56
"Power off handler not installed.\n");
57
return -ENODEV;
58
}
59
old_pm_power_off = pm_power_off;
60
pm_power_off = &iris_power_off;
61
printk(KERN_INFO "Iris power_off handler installed.\n");
62
return 0;
63
}
64
65
static void iris_remove(struct platform_device *pdev)
66
{
67
pm_power_off = old_pm_power_off;
68
printk(KERN_INFO "Iris power_off handler uninstalled.\n");
69
}
70
71
static struct platform_driver iris_driver = {
72
.driver = {
73
.name = "iris",
74
},
75
.probe = iris_probe,
76
.remove = iris_remove,
77
};
78
79
static struct resource iris_resources[] = {
80
{
81
.start = IRIS_GIO_BASE,
82
.end = IRIS_GIO_OUTPUT,
83
.flags = IORESOURCE_IO,
84
.name = "address"
85
}
86
};
87
88
static struct platform_device *iris_device;
89
90
static int iris_init(void)
91
{
92
int ret;
93
if (force != 1) {
94
printk(KERN_ERR "The force parameter has not been set to 1."
95
" The Iris poweroff handler will not be installed.\n");
96
return -ENODEV;
97
}
98
ret = platform_driver_register(&iris_driver);
99
if (ret < 0) {
100
printk(KERN_ERR "Failed to register iris platform driver: %d\n",
101
ret);
102
return ret;
103
}
104
iris_device = platform_device_register_simple("iris", (-1),
105
iris_resources, ARRAY_SIZE(iris_resources));
106
if (IS_ERR(iris_device)) {
107
printk(KERN_ERR "Failed to register iris platform device\n");
108
platform_driver_unregister(&iris_driver);
109
return PTR_ERR(iris_device);
110
}
111
return 0;
112
}
113
114
static void iris_exit(void)
115
{
116
platform_device_unregister(iris_device);
117
platform_driver_unregister(&iris_driver);
118
}
119
120
module_init(iris_init);
121
module_exit(iris_exit);
122
123