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