Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 
0003 #define pr_fmt(fmt) "ipmi_hardcode: " fmt
0004 
0005 #include <linux/moduleparam.h>
0006 #include <linux/platform_device.h>
0007 #include "ipmi_si.h"
0008 #include "ipmi_plat_data.h"
0009 
0010 /*
0011  * There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
0012  * a default IO port, and 1 ACPI/SPMI address.  That sets SI_MAX_DRIVERS.
0013  */
0014 
0015 #define SI_MAX_PARMS 4
0016 
0017 #define MAX_SI_TYPE_STR 30
0018 static char          si_type_str[MAX_SI_TYPE_STR] __initdata;
0019 static unsigned long addrs[SI_MAX_PARMS];
0020 static unsigned int num_addrs;
0021 static unsigned int  ports[SI_MAX_PARMS];
0022 static unsigned int num_ports;
0023 static int           irqs[SI_MAX_PARMS] __initdata;
0024 static unsigned int num_irqs __initdata;
0025 static int           regspacings[SI_MAX_PARMS] __initdata;
0026 static unsigned int num_regspacings __initdata;
0027 static int           regsizes[SI_MAX_PARMS] __initdata;
0028 static unsigned int num_regsizes __initdata;
0029 static int           regshifts[SI_MAX_PARMS] __initdata;
0030 static unsigned int num_regshifts __initdata;
0031 static int slave_addrs[SI_MAX_PARMS] __initdata;
0032 static unsigned int num_slave_addrs __initdata;
0033 
0034 module_param_string(type, si_type_str, MAX_SI_TYPE_STR, 0);
0035 MODULE_PARM_DESC(type,
0036          "Defines the type of each interface, each interface separated by commas.  The types are 'kcs', 'smic', and 'bt'.  For example si_type=kcs,bt will set the first interface to kcs and the second to bt");
0037 module_param_hw_array(addrs, ulong, iomem, &num_addrs, 0);
0038 MODULE_PARM_DESC(addrs,
0039          "Sets the memory address of each interface, the addresses separated by commas.  Only use if an interface is in memory.  Otherwise, set it to zero or leave it blank.");
0040 module_param_hw_array(ports, uint, ioport, &num_ports, 0);
0041 MODULE_PARM_DESC(ports,
0042          "Sets the port address of each interface, the addresses separated by commas.  Only use if an interface is a port.  Otherwise, set it to zero or leave it blank.");
0043 module_param_hw_array(irqs, int, irq, &num_irqs, 0);
0044 MODULE_PARM_DESC(irqs,
0045          "Sets the interrupt of each interface, the addresses separated by commas.  Only use if an interface has an interrupt.  Otherwise, set it to zero or leave it blank.");
0046 module_param_hw_array(regspacings, int, other, &num_regspacings, 0);
0047 MODULE_PARM_DESC(regspacings,
0048          "The number of bytes between the start address and each successive register used by the interface.  For instance, if the start address is 0xca2 and the spacing is 2, then the second address is at 0xca4.  Defaults to 1.");
0049 module_param_hw_array(regsizes, int, other, &num_regsizes, 0);
0050 MODULE_PARM_DESC(regsizes,
0051          "The size of the specific IPMI register in bytes. This should generally be 1, 2, 4, or 8 for an 8-bit, 16-bit, 32-bit, or 64-bit register.  Use this if you the 8-bit IPMI register has to be read from a larger register.");
0052 module_param_hw_array(regshifts, int, other, &num_regshifts, 0);
0053 MODULE_PARM_DESC(regshifts,
0054          "The amount to shift the data read from the. IPMI register, in bits.  For instance, if the data is read from a 32-bit word and the IPMI data is in bit 8-15, then the shift would be 8");
0055 module_param_hw_array(slave_addrs, int, other, &num_slave_addrs, 0);
0056 MODULE_PARM_DESC(slave_addrs,
0057          "Set the default IPMB slave address for the controller.  Normally this is 0x20, but can be overridden by this parm.  This is an array indexed by interface number.");
0058 
0059 static void __init ipmi_hardcode_init_one(const char *si_type_str,
0060                       unsigned int i,
0061                       unsigned long addr,
0062                       enum ipmi_addr_space addr_space)
0063 {
0064     struct ipmi_plat_data p;
0065     int t;
0066 
0067     memset(&p, 0, sizeof(p));
0068 
0069     p.iftype = IPMI_PLAT_IF_SI;
0070     if (!si_type_str || !*si_type_str) {
0071         p.type = SI_KCS;
0072     } else {
0073         t = match_string(si_to_str, -1, si_type_str);
0074         if (t < 0) {
0075             pr_warn("Interface type specified for interface %d, was invalid: %s\n",
0076                 i, si_type_str);
0077             return;
0078         }
0079         p.type = t;
0080     }
0081 
0082     p.regsize = regsizes[i];
0083     p.slave_addr = slave_addrs[i];
0084     p.addr_source = SI_HARDCODED;
0085     p.regshift = regshifts[i];
0086     p.regsize = regsizes[i];
0087     p.addr = addr;
0088     p.space = addr_space;
0089 
0090     ipmi_platform_add("hardcode-ipmi-si", i, &p);
0091 }
0092 
0093 void __init ipmi_hardcode_init(void)
0094 {
0095     unsigned int i;
0096     char *str;
0097     char *si_type[SI_MAX_PARMS];
0098 
0099     memset(si_type, 0, sizeof(si_type));
0100 
0101     /* Parse out the si_type string into its components. */
0102     str = si_type_str;
0103     if (*str != '\0') {
0104         for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) {
0105             si_type[i] = str;
0106             str = strchr(str, ',');
0107             if (str) {
0108                 *str = '\0';
0109                 str++;
0110             } else {
0111                 break;
0112             }
0113         }
0114     }
0115 
0116     for (i = 0; i < SI_MAX_PARMS; i++) {
0117         if (i < num_ports && ports[i])
0118             ipmi_hardcode_init_one(si_type[i], i, ports[i],
0119                            IPMI_IO_ADDR_SPACE);
0120         if (i < num_addrs && addrs[i])
0121             ipmi_hardcode_init_one(si_type[i], i, addrs[i],
0122                            IPMI_MEM_ADDR_SPACE);
0123     }
0124 }
0125 
0126 
0127 void ipmi_si_hardcode_exit(void)
0128 {
0129     ipmi_remove_platform_device_by_name("hardcode-ipmi-si");
0130 }
0131 
0132 /*
0133  * Returns true of the given address exists as a hardcoded address,
0134  * false if not.
0135  */
0136 int ipmi_si_hardcode_match(int addr_space, unsigned long addr)
0137 {
0138     unsigned int i;
0139 
0140     if (addr_space == IPMI_IO_ADDR_SPACE) {
0141         for (i = 0; i < num_ports; i++) {
0142             if (ports[i] == addr)
0143                 return 1;
0144         }
0145     } else {
0146         for (i = 0; i < num_addrs; i++) {
0147             if (addrs[i] == addr)
0148                 return 1;
0149         }
0150     }
0151 
0152     return 0;
0153 }