819-v6.6-0012-nvmem-sec-qfprom-Add-Qualcomm-secure-QFPROM-support.patch 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. From 0a9ec38c47c1ca4528aa058e2b9ea61901a7e632 Mon Sep 17 00:00:00 2001
  2. From: Komal Bajaj <[email protected]>
  3. Date: Tue, 1 Aug 2023 12:10:25 +0530
  4. Subject: [PATCH] nvmem: sec-qfprom: Add Qualcomm secure QFPROM support
  5. For some of the Qualcomm SoC's, it is possible that
  6. some of the fuse regions or entire qfprom region is
  7. protected from non-secure access. In such situations,
  8. the OS will have to use secure calls to read the region.
  9. With that motivation, add secure qfprom driver.
  10. Signed-off-by: Komal Bajaj <[email protected]>
  11. Signed-off-by: Srinivas Kandagatla <[email protected]>
  12. ---
  13. drivers/nvmem/Kconfig | 13 ++++++
  14. drivers/nvmem/Makefile | 2 +
  15. drivers/nvmem/sec-qfprom.c | 96 ++++++++++++++++++++++++++++++++++++++
  16. 3 files changed, 111 insertions(+)
  17. create mode 100644 drivers/nvmem/sec-qfprom.c
  18. --- a/drivers/nvmem/Kconfig
  19. +++ b/drivers/nvmem/Kconfig
  20. @@ -226,6 +226,19 @@ config NVMEM_QCOM_QFPROM
  21. This driver can also be built as a module. If so, the module
  22. will be called nvmem_qfprom.
  23. +config NVMEM_QCOM_SEC_QFPROM
  24. + tristate "QCOM SECURE QFPROM Support"
  25. + depends on ARCH_QCOM || COMPILE_TEST
  26. + depends on HAS_IOMEM
  27. + depends on OF
  28. + select QCOM_SCM
  29. + help
  30. + Say y here to enable secure QFPROM support. The secure QFPROM provides access
  31. + functions for QFPROM data to rest of the drivers via nvmem interface.
  32. +
  33. + This driver can also be built as a module. If so, the module will be called
  34. + nvmem_sec_qfprom.
  35. +
  36. config NVMEM_RAVE_SP_EEPROM
  37. tristate "Rave SP EEPROM Support"
  38. depends on RAVE_SP_CORE
  39. --- a/drivers/nvmem/Makefile
  40. +++ b/drivers/nvmem/Makefile
  41. @@ -46,6 +46,8 @@ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvme
  42. nvmem-nintendo-otp-y := nintendo-otp.o
  43. obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
  44. nvmem_qfprom-y := qfprom.o
  45. +obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o
  46. +nvmem_sec_qfprom-y := sec-qfprom.o
  47. obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
  48. nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
  49. obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
  50. --- /dev/null
  51. +++ b/drivers/nvmem/sec-qfprom.c
  52. @@ -0,0 +1,96 @@
  53. +// SPDX-License-Identifier: GPL-2.0-only
  54. +/*
  55. + * Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
  56. + */
  57. +
  58. +#include <linux/firmware/qcom/qcom_scm.h>
  59. +#include <linux/mod_devicetable.h>
  60. +#include <linux/nvmem-provider.h>
  61. +#include <linux/platform_device.h>
  62. +#include <linux/pm_runtime.h>
  63. +
  64. +/**
  65. + * struct sec_qfprom - structure holding secure qfprom attributes
  66. + *
  67. + * @base: starting physical address for secure qfprom corrected address space.
  68. + * @dev: qfprom device structure.
  69. + */
  70. +struct sec_qfprom {
  71. + phys_addr_t base;
  72. + struct device *dev;
  73. +};
  74. +
  75. +static int sec_qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes)
  76. +{
  77. + struct sec_qfprom *priv = context;
  78. + unsigned int i;
  79. + u8 *val = _val;
  80. + u32 read_val;
  81. + u8 *tmp;
  82. +
  83. + for (i = 0; i < bytes; i++, reg++) {
  84. + if (i == 0 || reg % 4 == 0) {
  85. + if (qcom_scm_io_readl(priv->base + (reg & ~3), &read_val)) {
  86. + dev_err(priv->dev, "Couldn't access fuse register\n");
  87. + return -EINVAL;
  88. + }
  89. + tmp = (u8 *)&read_val;
  90. + }
  91. +
  92. + val[i] = tmp[reg & 3];
  93. + }
  94. +
  95. + return 0;
  96. +}
  97. +
  98. +static int sec_qfprom_probe(struct platform_device *pdev)
  99. +{
  100. + struct nvmem_config econfig = {
  101. + .name = "sec-qfprom",
  102. + .stride = 1,
  103. + .word_size = 1,
  104. + .id = NVMEM_DEVID_AUTO,
  105. + .reg_read = sec_qfprom_reg_read,
  106. + };
  107. + struct device *dev = &pdev->dev;
  108. + struct nvmem_device *nvmem;
  109. + struct sec_qfprom *priv;
  110. + struct resource *res;
  111. +
  112. + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  113. + if (!priv)
  114. + return -ENOMEM;
  115. +
  116. + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  117. + if (!res)
  118. + return -EINVAL;
  119. +
  120. + priv->base = res->start;
  121. +
  122. + econfig.size = resource_size(res);
  123. + econfig.dev = dev;
  124. + econfig.priv = priv;
  125. +
  126. + priv->dev = dev;
  127. +
  128. + nvmem = devm_nvmem_register(dev, &econfig);
  129. +
  130. + return PTR_ERR_OR_ZERO(nvmem);
  131. +}
  132. +
  133. +static const struct of_device_id sec_qfprom_of_match[] = {
  134. + { .compatible = "qcom,sec-qfprom" },
  135. + {/* sentinel */},
  136. +};
  137. +MODULE_DEVICE_TABLE(of, sec_qfprom_of_match);
  138. +
  139. +static struct platform_driver qfprom_driver = {
  140. + .probe = sec_qfprom_probe,
  141. + .driver = {
  142. + .name = "qcom_sec_qfprom",
  143. + .of_match_table = sec_qfprom_of_match,
  144. + },
  145. +};
  146. +module_platform_driver(qfprom_driver);
  147. +MODULE_DESCRIPTION("Qualcomm Secure QFPROM driver");
  148. +MODULE_LICENSE("GPL");