Skip to content

Commit c471245

Browse files
Komal-Bajajgregkh
authored andcommitted
nvmem: sec-qfprom: Add Qualcomm secure QFPROM support
For some of the Qualcomm SoC's, it is possible that some of the fuse regions or entire qfprom region is protected from non-secure access. In such situations, the OS will have to use secure calls to read the region. With that motivation, add secure qfprom driver. Signed-off-by: Komal Bajaj <[email protected]> Signed-off-by: Srinivas Kandagatla <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fcdc6d7 commit c471245

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

drivers/nvmem/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,19 @@ config NVMEM_QCOM_QFPROM
226226
This driver can also be built as a module. If so, the module
227227
will be called nvmem_qfprom.
228228

229+
config NVMEM_QCOM_SEC_QFPROM
230+
tristate "QCOM SECURE QFPROM Support"
231+
depends on ARCH_QCOM || COMPILE_TEST
232+
depends on HAS_IOMEM
233+
depends on OF
234+
select QCOM_SCM
235+
help
236+
Say y here to enable secure QFPROM support. The secure QFPROM provides access
237+
functions for QFPROM data to rest of the drivers via nvmem interface.
238+
239+
This driver can also be built as a module. If so, the module will be called
240+
nvmem_sec_qfprom.
241+
229242
config NVMEM_RAVE_SP_EEPROM
230243
tristate "Rave SP EEPROM Support"
231244
depends on RAVE_SP_CORE

drivers/nvmem/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ obj-$(CONFIG_NVMEM_NINTENDO_OTP) += nvmem-nintendo-otp.o
4646
nvmem-nintendo-otp-y := nintendo-otp.o
4747
obj-$(CONFIG_NVMEM_QCOM_QFPROM) += nvmem_qfprom.o
4848
nvmem_qfprom-y := qfprom.o
49+
obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o
50+
nvmem_sec_qfprom-y := sec-qfprom.o
4951
obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
5052
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
5153
obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o

drivers/nvmem/sec-qfprom.c

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/*
3+
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
4+
*/
5+
6+
#include <linux/firmware/qcom/qcom_scm.h>
7+
#include <linux/mod_devicetable.h>
8+
#include <linux/nvmem-provider.h>
9+
#include <linux/platform_device.h>
10+
#include <linux/pm_runtime.h>
11+
12+
/**
13+
* struct sec_qfprom - structure holding secure qfprom attributes
14+
*
15+
* @base: starting physical address for secure qfprom corrected address space.
16+
* @dev: qfprom device structure.
17+
*/
18+
struct sec_qfprom {
19+
phys_addr_t base;
20+
struct device *dev;
21+
};
22+
23+
static int sec_qfprom_reg_read(void *context, unsigned int reg, void *_val, size_t bytes)
24+
{
25+
struct sec_qfprom *priv = context;
26+
unsigned int i;
27+
u8 *val = _val;
28+
u32 read_val;
29+
u8 *tmp;
30+
31+
for (i = 0; i < bytes; i++, reg++) {
32+
if (i == 0 || reg % 4 == 0) {
33+
if (qcom_scm_io_readl(priv->base + (reg & ~3), &read_val)) {
34+
dev_err(priv->dev, "Couldn't access fuse register\n");
35+
return -EINVAL;
36+
}
37+
tmp = (u8 *)&read_val;
38+
}
39+
40+
val[i] = tmp[reg & 3];
41+
}
42+
43+
return 0;
44+
}
45+
46+
static int sec_qfprom_probe(struct platform_device *pdev)
47+
{
48+
struct nvmem_config econfig = {
49+
.name = "sec-qfprom",
50+
.stride = 1,
51+
.word_size = 1,
52+
.id = NVMEM_DEVID_AUTO,
53+
.reg_read = sec_qfprom_reg_read,
54+
};
55+
struct device *dev = &pdev->dev;
56+
struct nvmem_device *nvmem;
57+
struct sec_qfprom *priv;
58+
struct resource *res;
59+
60+
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
61+
if (!priv)
62+
return -ENOMEM;
63+
64+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
65+
if (!res)
66+
return -EINVAL;
67+
68+
priv->base = res->start;
69+
70+
econfig.size = resource_size(res);
71+
econfig.dev = dev;
72+
econfig.priv = priv;
73+
74+
priv->dev = dev;
75+
76+
nvmem = devm_nvmem_register(dev, &econfig);
77+
78+
return PTR_ERR_OR_ZERO(nvmem);
79+
}
80+
81+
static const struct of_device_id sec_qfprom_of_match[] = {
82+
{ .compatible = "qcom,sec-qfprom" },
83+
{/* sentinel */},
84+
};
85+
MODULE_DEVICE_TABLE(of, sec_qfprom_of_match);
86+
87+
static struct platform_driver qfprom_driver = {
88+
.probe = sec_qfprom_probe,
89+
.driver = {
90+
.name = "qcom_sec_qfprom",
91+
.of_match_table = sec_qfprom_of_match,
92+
},
93+
};
94+
module_platform_driver(qfprom_driver);
95+
MODULE_DESCRIPTION("Qualcomm Secure QFPROM driver");
96+
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)