ipmi_si_hardcode.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // SPDX-License-Identifier: GPL-2.0+
  2. #include <linux/moduleparam.h>
  3. #include <linux/platform_device.h>
  4. #include "ipmi_si.h"
  5. #define PFX "ipmi_hardcode: "
  6. /*
  7. * There can be 4 IO ports passed in (with or without IRQs), 4 addresses,
  8. * a default IO port, and 1 ACPI/SPMI address. That sets SI_MAX_DRIVERS.
  9. */
  10. #define SI_MAX_PARMS 4
  11. #define MAX_SI_TYPE_STR 30
  12. static char si_type_str[MAX_SI_TYPE_STR] __initdata;
  13. static unsigned long addrs[SI_MAX_PARMS];
  14. static unsigned int num_addrs;
  15. static unsigned int ports[SI_MAX_PARMS];
  16. static unsigned int num_ports;
  17. static int irqs[SI_MAX_PARMS] __initdata;
  18. static unsigned int num_irqs __initdata;
  19. static int regspacings[SI_MAX_PARMS] __initdata;
  20. static unsigned int num_regspacings __initdata;
  21. static int regsizes[SI_MAX_PARMS] __initdata;
  22. static unsigned int num_regsizes __initdata;
  23. static int regshifts[SI_MAX_PARMS] __initdata;
  24. static unsigned int num_regshifts __initdata;
  25. static int slave_addrs[SI_MAX_PARMS] __initdata;
  26. static unsigned int num_slave_addrs __initdata;
  27. module_param_string(type, si_type_str, MAX_SI_TYPE_STR, 0);
  28. MODULE_PARM_DESC(type, "Defines the type of each interface, each"
  29. " interface separated by commas. The types are 'kcs',"
  30. " 'smic', and 'bt'. For example si_type=kcs,bt will set"
  31. " the first interface to kcs and the second to bt");
  32. module_param_hw_array(addrs, ulong, iomem, &num_addrs, 0);
  33. MODULE_PARM_DESC(addrs, "Sets the memory address of each interface, the"
  34. " addresses separated by commas. Only use if an interface"
  35. " is in memory. Otherwise, set it to zero or leave"
  36. " it blank.");
  37. module_param_hw_array(ports, uint, ioport, &num_ports, 0);
  38. MODULE_PARM_DESC(ports, "Sets the port address of each interface, the"
  39. " addresses separated by commas. Only use if an interface"
  40. " is a port. Otherwise, set it to zero or leave"
  41. " it blank.");
  42. module_param_hw_array(irqs, int, irq, &num_irqs, 0);
  43. MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the"
  44. " addresses separated by commas. Only use if an interface"
  45. " has an interrupt. Otherwise, set it to zero or leave"
  46. " it blank.");
  47. module_param_hw_array(regspacings, int, other, &num_regspacings, 0);
  48. MODULE_PARM_DESC(regspacings, "The number of bytes between the start address"
  49. " and each successive register used by the interface. For"
  50. " instance, if the start address is 0xca2 and the spacing"
  51. " is 2, then the second address is at 0xca4. Defaults"
  52. " to 1.");
  53. module_param_hw_array(regsizes, int, other, &num_regsizes, 0);
  54. MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes."
  55. " This should generally be 1, 2, 4, or 8 for an 8-bit,"
  56. " 16-bit, 32-bit, or 64-bit register. Use this if you"
  57. " the 8-bit IPMI register has to be read from a larger"
  58. " register.");
  59. module_param_hw_array(regshifts, int, other, &num_regshifts, 0);
  60. MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the."
  61. " IPMI register, in bits. For instance, if the data"
  62. " is read from a 32-bit word and the IPMI data is in"
  63. " bit 8-15, then the shift would be 8");
  64. module_param_hw_array(slave_addrs, int, other, &num_slave_addrs, 0);
  65. MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
  66. " the controller. Normally this is 0x20, but can be"
  67. " overridden by this parm. This is an array indexed"
  68. " by interface number.");
  69. static struct platform_device *ipmi_hc_pdevs[SI_MAX_PARMS];
  70. static void __init ipmi_hardcode_init_one(const char *si_type_str,
  71. unsigned int i,
  72. unsigned long addr,
  73. unsigned int flags)
  74. {
  75. struct platform_device *pdev;
  76. unsigned int num_r = 1, size;
  77. struct resource r[4];
  78. struct property_entry p[6];
  79. enum si_type si_type;
  80. unsigned int regspacing, regsize;
  81. int rv;
  82. memset(p, 0, sizeof(p));
  83. memset(r, 0, sizeof(r));
  84. if (!si_type_str || !*si_type_str || strcmp(si_type_str, "kcs") == 0) {
  85. size = 2;
  86. si_type = SI_KCS;
  87. } else if (strcmp(si_type_str, "smic") == 0) {
  88. size = 2;
  89. si_type = SI_SMIC;
  90. } else if (strcmp(si_type_str, "bt") == 0) {
  91. size = 3;
  92. si_type = SI_BT;
  93. } else if (strcmp(si_type_str, "invalid") == 0) {
  94. /*
  95. * Allow a firmware-specified interface to be
  96. * disabled.
  97. */
  98. size = 1;
  99. si_type = SI_TYPE_INVALID;
  100. } else {
  101. pr_warn("Interface type specified for interface %d, was invalid: %s\n",
  102. i, si_type_str);
  103. return;
  104. }
  105. regsize = regsizes[i];
  106. if (regsize == 0)
  107. regsize = DEFAULT_REGSIZE;
  108. p[0] = PROPERTY_ENTRY_U8("ipmi-type", si_type);
  109. p[1] = PROPERTY_ENTRY_U8("slave-addr", slave_addrs[i]);
  110. p[2] = PROPERTY_ENTRY_U8("addr-source", SI_HARDCODED);
  111. p[3] = PROPERTY_ENTRY_U8("reg-shift", regshifts[i]);
  112. p[4] = PROPERTY_ENTRY_U8("reg-size", regsize);
  113. /* Last entry must be left NULL to terminate it. */
  114. /*
  115. * Register spacing is derived from the resources in
  116. * the IPMI platform code.
  117. */
  118. regspacing = regspacings[i];
  119. if (regspacing == 0)
  120. regspacing = regsize;
  121. r[0].start = addr;
  122. r[0].end = r[0].start + regsize - 1;
  123. r[0].name = "IPMI Address 1";
  124. r[0].flags = flags;
  125. if (size > 1) {
  126. r[1].start = r[0].start + regspacing;
  127. r[1].end = r[1].start + regsize - 1;
  128. r[1].name = "IPMI Address 2";
  129. r[1].flags = flags;
  130. num_r++;
  131. }
  132. if (size > 2) {
  133. r[2].start = r[1].start + regspacing;
  134. r[2].end = r[2].start + regsize - 1;
  135. r[2].name = "IPMI Address 3";
  136. r[2].flags = flags;
  137. num_r++;
  138. }
  139. if (irqs[i]) {
  140. r[num_r].start = irqs[i];
  141. r[num_r].end = irqs[i];
  142. r[num_r].name = "IPMI IRQ";
  143. r[num_r].flags = IORESOURCE_IRQ;
  144. num_r++;
  145. }
  146. pdev = platform_device_alloc("hardcode-ipmi-si", i);
  147. if (!pdev) {
  148. pr_err("Error allocating IPMI platform device %d\n", i);
  149. return;
  150. }
  151. rv = platform_device_add_resources(pdev, r, num_r);
  152. if (rv) {
  153. dev_err(&pdev->dev,
  154. "Unable to add hard-code resources: %d\n", rv);
  155. goto err;
  156. }
  157. rv = platform_device_add_properties(pdev, p);
  158. if (rv) {
  159. dev_err(&pdev->dev,
  160. "Unable to add hard-code properties: %d\n", rv);
  161. goto err;
  162. }
  163. rv = platform_device_add(pdev);
  164. if (rv) {
  165. dev_err(&pdev->dev,
  166. "Unable to add hard-code device: %d\n", rv);
  167. goto err;
  168. }
  169. ipmi_hc_pdevs[i] = pdev;
  170. return;
  171. err:
  172. platform_device_put(pdev);
  173. }
  174. void __init ipmi_hardcode_init(void)
  175. {
  176. unsigned int i;
  177. char *str;
  178. char *si_type[SI_MAX_PARMS];
  179. memset(si_type, 0, sizeof(si_type));
  180. /* Parse out the si_type string into its components. */
  181. str = si_type_str;
  182. if (*str != '\0') {
  183. for (i = 0; (i < SI_MAX_PARMS) && (*str != '\0'); i++) {
  184. si_type[i] = str;
  185. str = strchr(str, ',');
  186. if (str) {
  187. *str = '\0';
  188. str++;
  189. } else {
  190. break;
  191. }
  192. }
  193. }
  194. for (i = 0; i < SI_MAX_PARMS; i++) {
  195. if (i < num_ports && ports[i])
  196. ipmi_hardcode_init_one(si_type[i], i, ports[i],
  197. IORESOURCE_IO);
  198. if (i < num_addrs && addrs[i])
  199. ipmi_hardcode_init_one(si_type[i], i, addrs[i],
  200. IORESOURCE_MEM);
  201. }
  202. }
  203. void ipmi_si_hardcode_exit(void)
  204. {
  205. unsigned int i;
  206. for (i = 0; i < SI_MAX_PARMS; i++) {
  207. if (ipmi_hc_pdevs[i])
  208. platform_device_unregister(ipmi_hc_pdevs[i]);
  209. }
  210. }
  211. /*
  212. * Returns true of the given address exists as a hardcoded address,
  213. * false if not.
  214. */
  215. int ipmi_si_hardcode_match(int addr_type, unsigned long addr)
  216. {
  217. unsigned int i;
  218. if (addr_type == IPMI_IO_ADDR_SPACE) {
  219. for (i = 0; i < num_ports; i++) {
  220. if (ports[i] == addr)
  221. return 1;
  222. }
  223. } else {
  224. for (i = 0; i < num_addrs; i++) {
  225. if (addrs[i] == addr)
  226. return 1;
  227. }
  228. }
  229. return 0;
  230. }