ipmi_plat_data.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * Add an IPMI platform device.
  4. */
  5. #include <linux/platform_device.h>
  6. #include "ipmi_plat_data.h"
  7. #include "ipmi_si.h"
  8. struct platform_device *ipmi_platform_add(const char *name, unsigned int inst,
  9. struct ipmi_plat_data *p)
  10. {
  11. struct platform_device *pdev;
  12. unsigned int num_r = 1, size = 0, pidx = 0;
  13. struct resource r[4];
  14. struct property_entry pr[6];
  15. u32 flags;
  16. int rv;
  17. memset(pr, 0, sizeof(pr));
  18. memset(r, 0, sizeof(r));
  19. if (p->iftype == IPMI_PLAT_IF_SI) {
  20. if (p->type == SI_BT)
  21. size = 3;
  22. else if (p->type != SI_TYPE_INVALID)
  23. size = 2;
  24. if (p->regsize == 0)
  25. p->regsize = DEFAULT_REGSIZE;
  26. if (p->regspacing == 0)
  27. p->regspacing = p->regsize;
  28. pr[pidx++] = PROPERTY_ENTRY_U8("ipmi-type", p->type);
  29. } else if (p->iftype == IPMI_PLAT_IF_SSIF) {
  30. pr[pidx++] = PROPERTY_ENTRY_U16("i2c-addr", p->addr);
  31. }
  32. if (p->slave_addr)
  33. pr[pidx++] = PROPERTY_ENTRY_U8("slave-addr", p->slave_addr);
  34. pr[pidx++] = PROPERTY_ENTRY_U8("addr-source", p->addr_source);
  35. if (p->regshift)
  36. pr[pidx++] = PROPERTY_ENTRY_U8("reg-shift", p->regshift);
  37. pr[pidx++] = PROPERTY_ENTRY_U8("reg-size", p->regsize);
  38. /* Last entry must be left NULL to terminate it. */
  39. pdev = platform_device_alloc(name, inst);
  40. if (!pdev) {
  41. pr_err("Error allocating IPMI platform device %s.%d\n",
  42. name, inst);
  43. return NULL;
  44. }
  45. if (size == 0)
  46. /* An invalid or SSIF interface, no resources. */
  47. goto add_properties;
  48. /*
  49. * Register spacing is derived from the resources in
  50. * the IPMI platform code.
  51. */
  52. if (p->space == IPMI_IO_ADDR_SPACE)
  53. flags = IORESOURCE_IO;
  54. else
  55. flags = IORESOURCE_MEM;
  56. r[0].start = p->addr;
  57. r[0].end = r[0].start + p->regsize - 1;
  58. r[0].name = "IPMI Address 1";
  59. r[0].flags = flags;
  60. if (size > 1) {
  61. r[1].start = r[0].start + p->regspacing;
  62. r[1].end = r[1].start + p->regsize - 1;
  63. r[1].name = "IPMI Address 2";
  64. r[1].flags = flags;
  65. num_r++;
  66. }
  67. if (size > 2) {
  68. r[2].start = r[1].start + p->regspacing;
  69. r[2].end = r[2].start + p->regsize - 1;
  70. r[2].name = "IPMI Address 3";
  71. r[2].flags = flags;
  72. num_r++;
  73. }
  74. if (p->irq) {
  75. r[num_r].start = p->irq;
  76. r[num_r].end = p->irq;
  77. r[num_r].name = "IPMI IRQ";
  78. r[num_r].flags = IORESOURCE_IRQ;
  79. num_r++;
  80. }
  81. rv = platform_device_add_resources(pdev, r, num_r);
  82. if (rv) {
  83. dev_err(&pdev->dev,
  84. "Unable to add hard-code resources: %d\n", rv);
  85. goto err;
  86. }
  87. add_properties:
  88. rv = device_create_managed_software_node(&pdev->dev, pr, NULL);
  89. if (rv) {
  90. dev_err(&pdev->dev,
  91. "Unable to add hard-code properties: %d\n", rv);
  92. goto err;
  93. }
  94. rv = platform_device_add(pdev);
  95. if (rv) {
  96. dev_err(&pdev->dev,
  97. "Unable to add hard-code device: %d\n", rv);
  98. goto err;
  99. }
  100. return pdev;
  101. err:
  102. platform_device_put(pdev);
  103. return NULL;
  104. }
  105. EXPORT_SYMBOL(ipmi_platform_add);