root/drivers/platform/x86/ibm_rtl.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtl_port_map
  2. rtl_port_unmap
  3. ibm_rtl_write
  4. rtl_show_version
  5. rtl_show_state
  6. rtl_set_state
  7. rtl_setup_sysfs
  8. rtl_teardown_sysfs
  9. ibm_rtl_init
  10. ibm_rtl_exit

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

/* [<][>][^][v][top][bottom][index][help] */