xref: /linux/drivers/platform/x86/ibm_rtl.c (revision f2ee442115c9b6219083c019939a9cc0c9abb2f8)
1 /*
2  * IBM Real-Time Linux driver
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  * Copyright (C) IBM Corporation, 2010
19  *
20  * Author: Keith Mannthey <kmannth@us.ibm.com>
21  *         Vernon Mauery <vernux@us.ibm.com>
22  *
23  */
24 
25 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
26 
27 #include <linux/kernel.h>
28 #include <linux/delay.h>
29 #include <linux/module.h>
30 #include <linux/io.h>
31 #include <linux/sysdev.h>
32 #include <linux/dmi.h>
33 #include <linux/efi.h>
34 #include <linux/mutex.h>
35 #include <asm/bios_ebda.h>
36 
37 static bool force;
38 module_param(force, bool, 0);
39 MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");
40 
41 static bool debug;
42 module_param(debug, bool, 0644);
43 MODULE_PARM_DESC(debug, "Show debug output");
44 
45 MODULE_LICENSE("GPL");
46 MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");
47 MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");
48 
49 #define RTL_ADDR_TYPE_IO    1
50 #define RTL_ADDR_TYPE_MMIO  2
51 
52 #define RTL_CMD_ENTER_PRTM  1
53 #define RTL_CMD_EXIT_PRTM   2
54 
55 /* The RTL table as presented by the EBDA: */
56 struct ibm_rtl_table {
57 	char signature[5]; /* signature should be "_RTL_" */
58 	u8 version;
59 	u8 rt_status;
60 	u8 command;
61 	u8 command_status;
62 	u8 cmd_address_type;
63 	u8 cmd_granularity;
64 	u8 cmd_offset;
65 	u16 reserve1;
66 	u32 cmd_port_address; /* platform dependent address */
67 	u32 cmd_port_value;   /* platform dependent value */
68 } __attribute__((packed));
69 
70 /* to locate "_RTL_" signature do a masked 5-byte integer compare */
71 #define RTL_SIGNATURE 0x0000005f4c54525fULL
72 #define RTL_MASK      0x000000ffffffffffULL
73 
74 #define RTL_DEBUG(fmt, ...)				\
75 do {							\
76 	if (debug)					\
77 		pr_info(fmt, ##__VA_ARGS__);		\
78 } while (0)
79 
80 static DEFINE_MUTEX(rtl_lock);
81 static struct ibm_rtl_table __iomem *rtl_table;
82 static void __iomem *ebda_map;
83 static void __iomem *rtl_cmd_addr;
84 static u8 rtl_cmd_type;
85 static u8 rtl_cmd_width;
86 
87 #ifndef readq
88 static inline __u64 readq(const volatile void __iomem *addr)
89 {
90 	const volatile u32 __iomem *p = addr;
91 	u32 low, high;
92 
93 	low = readl(p);
94 	high = readl(p + 1);
95 
96 	return low + ((u64)high << 32);
97 }
98 #endif
99 
100 static void __iomem *rtl_port_map(phys_addr_t addr, unsigned long len)
101 {
102 	if (rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
103 		return ioremap(addr, len);
104 	return ioport_map(addr, len);
105 }
106 
107 static void rtl_port_unmap(void __iomem *addr)
108 {
109 	if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)
110 		iounmap(addr);
111 	else
112 		ioport_unmap(addr);
113 }
114 
115 static int ibm_rtl_write(u8 value)
116 {
117 	int ret = 0, count = 0;
118 	static u32 cmd_port_val;
119 
120 	RTL_DEBUG("%s(%d)\n", __func__, value);
121 
122 	value = value == 1 ? RTL_CMD_ENTER_PRTM : RTL_CMD_EXIT_PRTM;
123 
124 	mutex_lock(&rtl_lock);
125 
126 	if (ioread8(&rtl_table->rt_status) != value) {
127 		iowrite8(value, &rtl_table->command);
128 
129 		switch (rtl_cmd_width) {
130 		case 8:
131 			cmd_port_val = ioread8(&rtl_table->cmd_port_value);
132 			RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
133 			iowrite8((u8)cmd_port_val, rtl_cmd_addr);
134 			break;
135 		case 16:
136 			cmd_port_val = ioread16(&rtl_table->cmd_port_value);
137 			RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
138 			iowrite16((u16)cmd_port_val, rtl_cmd_addr);
139 			break;
140 		case 32:
141 			cmd_port_val = ioread32(&rtl_table->cmd_port_value);
142 			RTL_DEBUG("cmd_port_val = %u\n", cmd_port_val);
143 			iowrite32(cmd_port_val, rtl_cmd_addr);
144 			break;
145 		}
146 
147 		while (ioread8(&rtl_table->command)) {
148 			msleep(10);
149 			if (count++ > 500) {
150 				pr_err("Hardware not responding to "
151 				       "mode switch request\n");
152 				ret = -EIO;
153 				break;
154 			}
155 
156 		}
157 
158 		if (ioread8(&rtl_table->command_status)) {
159 			RTL_DEBUG("command_status reports failed command\n");
160 			ret = -EIO;
161 		}
162 	}
163 
164 	mutex_unlock(&rtl_lock);
165 	return ret;
166 }
167 
168 static ssize_t rtl_show_version(struct sysdev_class * dev,
169                                 struct sysdev_class_attribute *attr,
170                                 char *buf)
171 {
172 	return sprintf(buf, "%d\n", (int)ioread8(&rtl_table->version));
173 }
174 
175 static ssize_t rtl_show_state(struct sysdev_class *dev,
176                               struct sysdev_class_attribute *attr,
177                               char *buf)
178 {
179 	return sprintf(buf, "%d\n", ioread8(&rtl_table->rt_status));
180 }
181 
182 static ssize_t rtl_set_state(struct sysdev_class *dev,
183                              struct sysdev_class_attribute *attr,
184                              const char *buf,
185                              size_t count)
186 {
187 	ssize_t ret;
188 
189 	if (count < 1 || count > 2)
190 		return -EINVAL;
191 
192 	switch (buf[0]) {
193 	case '0':
194 		ret = ibm_rtl_write(0);
195 		break;
196 	case '1':
197 		ret = ibm_rtl_write(1);
198 		break;
199 	default:
200 		ret = -EINVAL;
201 	}
202 	if (ret >= 0)
203 		ret = count;
204 
205 	return ret;
206 }
207 
208 static struct sysdev_class class_rtl = {
209 	.name = "ibm_rtl",
210 };
211 
212 static SYSDEV_CLASS_ATTR(version, S_IRUGO, rtl_show_version, NULL);
213 static SYSDEV_CLASS_ATTR(state, 0600, rtl_show_state, rtl_set_state);
214 
215 static struct sysdev_class_attribute *rtl_attributes[] = {
216 	&attr_version,
217 	&attr_state,
218 	NULL
219 };
220 
221 
222 static int rtl_setup_sysfs(void) {
223 	int ret, i;
224 	ret = sysdev_class_register(&class_rtl);
225 
226 	if (!ret) {
227 		for (i = 0; rtl_attributes[i]; i ++)
228 			sysdev_class_create_file(&class_rtl, rtl_attributes[i]);
229 	}
230 	return ret;
231 }
232 
233 static void rtl_teardown_sysfs(void) {
234 	int i;
235 	for (i = 0; rtl_attributes[i]; i ++)
236 		sysdev_class_remove_file(&class_rtl, rtl_attributes[i]);
237 	sysdev_class_unregister(&class_rtl);
238 }
239 
240 
241 static struct dmi_system_id __initdata ibm_rtl_dmi_table[] = {
242 	{                                                  \
243 		.matches = {                               \
244 			DMI_MATCH(DMI_SYS_VENDOR, "IBM"),  \
245 		},                                         \
246 	},
247 	{ }
248 };
249 
250 static int __init ibm_rtl_init(void) {
251 	unsigned long ebda_addr, ebda_size;
252 	unsigned int ebda_kb;
253 	int ret = -ENODEV, i;
254 
255 	if (force)
256 		pr_warn("module loaded by force\n");
257 	/* first ensure that we are running on IBM HW */
258 	else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
259 		return -ENODEV;
260 
261 	/* Get the address for the Extended BIOS Data Area */
262 	ebda_addr = get_bios_ebda();
263 	if (!ebda_addr) {
264 		RTL_DEBUG("no BIOS EBDA found\n");
265 		return -ENODEV;
266 	}
267 
268 	ebda_map = ioremap(ebda_addr, 4);
269 	if (!ebda_map)
270 		return -ENOMEM;
271 
272 	/* First word in the EDBA is the Size in KB */
273 	ebda_kb = ioread16(ebda_map);
274 	RTL_DEBUG("EBDA is %d kB\n", ebda_kb);
275 
276 	if (ebda_kb == 0)
277 		goto out;
278 
279 	iounmap(ebda_map);
280 	ebda_size = ebda_kb*1024;
281 
282 	/* Remap the whole table */
283 	ebda_map = ioremap(ebda_addr, ebda_size);
284 	if (!ebda_map)
285 		return -ENOMEM;
286 
287 	/* search for the _RTL_ signature at the start of the table */
288 	for (i = 0 ; i < ebda_size/sizeof(unsigned int); i++) {
289 		struct ibm_rtl_table __iomem * tmp;
290 		tmp = (struct ibm_rtl_table __iomem *) (ebda_map+i);
291 		if ((readq(&tmp->signature) & RTL_MASK) == RTL_SIGNATURE) {
292 			phys_addr_t addr;
293 			unsigned int plen;
294 			RTL_DEBUG("found RTL_SIGNATURE at %p\n", tmp);
295 			rtl_table = tmp;
296 			/* The address, value, width and offset are platform
297 			 * dependent and found in the ibm_rtl_table */
298 			rtl_cmd_width = ioread8(&rtl_table->cmd_granularity);
299 			rtl_cmd_type = ioread8(&rtl_table->cmd_address_type);
300 			RTL_DEBUG("rtl_cmd_width = %u, rtl_cmd_type = %u\n",
301 				  rtl_cmd_width, rtl_cmd_type);
302 			addr = ioread32(&rtl_table->cmd_port_address);
303 			RTL_DEBUG("addr = %#llx\n", (unsigned long long)addr);
304 			plen = rtl_cmd_width/sizeof(char);
305 			rtl_cmd_addr = rtl_port_map(addr, plen);
306 			RTL_DEBUG("rtl_cmd_addr = %p\n", rtl_cmd_addr);
307 			if (!rtl_cmd_addr) {
308 				ret = -ENOMEM;
309 				break;
310 			}
311 			ret = rtl_setup_sysfs();
312 			break;
313 		}
314 	}
315 
316 out:
317 	if (ret) {
318 		iounmap(ebda_map);
319 		rtl_port_unmap(rtl_cmd_addr);
320 	}
321 
322 	return ret;
323 }
324 
325 static void __exit ibm_rtl_exit(void)
326 {
327 	if (rtl_table) {
328 		RTL_DEBUG("cleaning up");
329 		/* do not leave the machine in SMI-free mode */
330 		ibm_rtl_write(0);
331 		/* unmap, unlink and remove all traces */
332 		rtl_teardown_sysfs();
333 		iounmap(ebda_map);
334 		rtl_port_unmap(rtl_cmd_addr);
335 	}
336 }
337 
338 module_init(ibm_rtl_init);
339 module_exit(ibm_rtl_exit);
340