326 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * IBM Real-Time Linux driver4 *5 * Copyright (C) IBM Corporation, 20106 *7 * Author: Keith Mannthey <kmannth@us.ibm.com>8 * Vernon Mauery <vernux@us.ibm.com>9 */10 11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt12 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 24static bool force;25module_param(force, bool, 0);26MODULE_PARM_DESC(force, "Force driver load, ignore DMI data");27 28static bool debug;29module_param(debug, bool, 0644);30MODULE_PARM_DESC(debug, "Show debug output");31 32MODULE_DESCRIPTION("IBM Premium Real Time Mode (PRTM) driver");33MODULE_LICENSE("GPL");34MODULE_AUTHOR("Keith Mannthey <kmmanth@us.ibm.com>");35MODULE_AUTHOR("Vernon Mauery <vernux@us.ibm.com>");36 37#define RTL_ADDR_TYPE_IO 138#define RTL_ADDR_TYPE_MMIO 239 40#define RTL_CMD_ENTER_PRTM 141#define RTL_CMD_EXIT_PRTM 242 43/* The RTL table as presented by the EBDA: */44struct 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 0x0000005f4c54525fULL60#define RTL_MASK 0x000000ffffffffffULL61 62#define RTL_DEBUG(fmt, ...) \63do { \64 if (debug) \65 pr_info(fmt, ##__VA_ARGS__); \66} while (0)67 68static DEFINE_MUTEX(rtl_lock);69static struct ibm_rtl_table __iomem *rtl_table;70static void __iomem *ebda_map;71static void __iomem *rtl_cmd_addr;72static u8 rtl_cmd_type;73static u8 rtl_cmd_width;74 75static 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 82static void rtl_port_unmap(void __iomem *addr)83{84 if (addr && rtl_cmd_type == RTL_ADDR_TYPE_MMIO)85 iounmap(addr);86 else87 ioport_unmap(addr);88}89 90static 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 143static 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 150static 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 157static 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 183static const struct bus_type rtl_subsys = {184 .name = "ibm_rtl",185 .dev_name = "ibm_rtl",186};187 188static DEVICE_ATTR(version, S_IRUGO, rtl_show_version, NULL);189static DEVICE_ATTR(state, 0600, rtl_show_state, rtl_set_state);190 191static struct device_attribute *rtl_attributes[] = {192 &dev_attr_version,193 &dev_attr_state,194 NULL195};196 197 198static 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 214static 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 227static 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 236static 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 platform283 * 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 302out:303 if (ret) {304 iounmap(ebda_map);305 rtl_port_unmap(rtl_cmd_addr);306 }307 308 return ret;309}310 311static 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 324module_init(ibm_rtl_init);325module_exit(ibm_rtl_exit);326