opal-nvram.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * PowerNV nvram code.
  4. *
  5. * Copyright 2011 IBM Corp.
  6. */
  7. #define DEBUG
  8. #include <linux/delay.h>
  9. #include <linux/kernel.h>
  10. #include <linux/init.h>
  11. #include <linux/of.h>
  12. #include <asm/opal.h>
  13. #include <asm/nvram.h>
  14. #include <asm/machdep.h>
  15. static unsigned int nvram_size;
  16. static ssize_t opal_nvram_size(void)
  17. {
  18. return nvram_size;
  19. }
  20. static ssize_t opal_nvram_read(char *buf, size_t count, loff_t *index)
  21. {
  22. s64 rc;
  23. int off;
  24. if (*index >= nvram_size)
  25. return 0;
  26. off = *index;
  27. if ((off + count) > nvram_size)
  28. count = nvram_size - off;
  29. rc = opal_read_nvram(__pa(buf), count, off);
  30. if (rc != OPAL_SUCCESS)
  31. return -EIO;
  32. *index += count;
  33. return count;
  34. }
  35. /*
  36. * This can be called in the panic path with interrupts off, so use
  37. * mdelay in that case.
  38. */
  39. static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
  40. {
  41. s64 rc = OPAL_BUSY;
  42. int off;
  43. if (*index >= nvram_size)
  44. return 0;
  45. off = *index;
  46. if ((off + count) > nvram_size)
  47. count = nvram_size - off;
  48. while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
  49. rc = opal_write_nvram(__pa(buf), count, off);
  50. if (rc == OPAL_BUSY_EVENT) {
  51. if (in_interrupt() || irqs_disabled())
  52. mdelay(OPAL_BUSY_DELAY_MS);
  53. else
  54. msleep(OPAL_BUSY_DELAY_MS);
  55. opal_poll_events(NULL);
  56. } else if (rc == OPAL_BUSY) {
  57. if (in_interrupt() || irqs_disabled())
  58. mdelay(OPAL_BUSY_DELAY_MS);
  59. else
  60. msleep(OPAL_BUSY_DELAY_MS);
  61. }
  62. }
  63. if (rc)
  64. return -EIO;
  65. *index += count;
  66. return count;
  67. }
  68. static int __init opal_nvram_init_log_partitions(void)
  69. {
  70. /* Scan nvram for partitions */
  71. nvram_scan_partitions();
  72. nvram_init_oops_partition(0);
  73. return 0;
  74. }
  75. machine_arch_initcall(powernv, opal_nvram_init_log_partitions);
  76. void __init opal_nvram_init(void)
  77. {
  78. struct device_node *np;
  79. const __be32 *nbytes_p;
  80. np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram");
  81. if (np == NULL)
  82. return;
  83. nbytes_p = of_get_property(np, "#bytes", NULL);
  84. if (!nbytes_p) {
  85. of_node_put(np);
  86. return;
  87. }
  88. nvram_size = be32_to_cpup(nbytes_p);
  89. pr_info("OPAL nvram setup, %u bytes\n", nvram_size);
  90. of_node_put(np);
  91. ppc_md.nvram_read = opal_nvram_read;
  92. ppc_md.nvram_write = opal_nvram_write;
  93. ppc_md.nvram_size = opal_nvram_size;
  94. }