Commit 477348db authored by Viresh Kumar's avatar Viresh Kumar

Merge branch 'cpufreq/arm/qcom-nvmem' into HEAD

Merge base changes for cpufreq support for IPQ8074.
parents 038ef0d9 e9104e73
......@@ -52,6 +52,8 @@ properties:
iommus:
maxItems: 1
dma-coherent: true
required:
- compatible
- reg
......
......@@ -17800,6 +17800,18 @@ S: Maintained
F: Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
F: drivers/mtd/nand/raw/qcom_nandc.c
QUALCOMM QSEECOM DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/firmware/qcom_qseecom.c
QUALCOMM QSEECOM UEFISECAPP DRIVER
M: Maximilian Luz <luzmaximilian@gmail.com>
L: linux-arm-msm@vger.kernel.org
S: Maintained
F: drivers/firmware/qcom_qseecom_uefisecapp.c
QUALCOMM RMNET DRIVER
M: Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com>
M: Sean Tranchetti <quic_stranche@quicinc.com>
......
......@@ -226,6 +226,38 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT
Say Y here to enable "download mode" by default.
config QCOM_QSEECOM
bool "Qualcomm QSEECOM interface driver"
depends on QCOM_SCM=y
help
Various Qualcomm SoCs have a Secure Execution Environment (SEE) running
in the Trust Zone. This module provides an interface to that via the
QSEECOM mechanism, using SCM calls.
The QSEECOM interface allows, among other things, access to applications
running in the SEE. An example of such an application is 'uefisecapp',
which is required to access UEFI variables on certain systems. If
selected, the interface will also attempt to detect and register client
devices for supported applications.
Select Y here to enable the QSEECOM interface driver.
config QCOM_QSEECOM_UEFISECAPP
bool "Qualcomm SEE UEFI Secure App client driver"
depends on QCOM_QSEECOM
depends on EFI
help
Various Qualcomm SoCs do not allow direct access to EFI variables.
Instead, these need to be accessed via the UEFI Secure Application
(uefisecapp), residing in the Secure Execution Environment (SEE).
This module provides a client driver for uefisecapp, installing efivar
operations to allow the kernel accessing EFI variables, and via that also
provide user-space with access to EFI variables via efivarfs.
Select Y here to provide access to EFI variables on the aforementioned
platforms.
config SYSFB
bool
select BOOT_VESA_SUPPORT
......
......@@ -20,6 +20,8 @@ obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
obj-$(CONFIG_QCOM_QSEECOM) += qcom_qseecom.o
obj-$(CONFIG_QCOM_QSEECOM_UEFISECAPP) += qcom_qseecom_uefisecapp.o
obj-$(CONFIG_SYSFB) += sysfb.o
obj-$(CONFIG_SYSFB_SIMPLEFB) += sysfb_simplefb.o
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Driver for Qualcomm Secure Execution Environment (SEE) interface (QSEECOM).
* Responsible for setting up and managing QSEECOM client devices.
*
* Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
*/
#include <linux/auxiliary_bus.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/firmware/qcom/qcom_qseecom.h>
#include <linux/firmware/qcom/qcom_scm.h>
struct qseecom_app_desc {
const char *app_name;
const char *dev_name;
};
static void qseecom_client_release(struct device *dev)
{
struct qseecom_client *client;
client = container_of(dev, struct qseecom_client, aux_dev.dev);
kfree(client);
}
static void qseecom_client_remove(void *data)
{
struct qseecom_client *client = data;
auxiliary_device_delete(&client->aux_dev);
auxiliary_device_uninit(&client->aux_dev);
}
static int qseecom_client_register(struct platform_device *qseecom_dev,
const struct qseecom_app_desc *desc)
{
struct qseecom_client *client;
u32 app_id;
int ret;
/* Try to find the app ID, skip device if not found */
ret = qcom_scm_qseecom_app_get_id(desc->app_name, &app_id);
if (ret)
return ret == -ENOENT ? 0 : ret;
dev_info(&qseecom_dev->dev, "setting up client for %s\n", desc->app_name);
/* Allocate and set-up the client device */
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
return -ENOMEM;
client->aux_dev.name = desc->dev_name;
client->aux_dev.dev.parent = &qseecom_dev->dev;
client->aux_dev.dev.release = qseecom_client_release;
client->app_id = app_id;
ret = auxiliary_device_init(&client->aux_dev);
if (ret) {
kfree(client);
return ret;
}
ret = auxiliary_device_add(&client->aux_dev);
if (ret) {
auxiliary_device_uninit(&client->aux_dev);
return ret;
}
ret = devm_add_action_or_reset(&qseecom_dev->dev, qseecom_client_remove, client);
if (ret)
return ret;
return 0;
}
/*
* List of supported applications. One client device will be created per entry,
* assuming the app has already been loaded (usually by firmware bootloaders)
* and its ID can be queried successfully.
*/
static const struct qseecom_app_desc qcom_qseecom_apps[] = {
{ "qcom.tz.uefisecapp", "uefisecapp" },
};
static int qcom_qseecom_probe(struct platform_device *qseecom_dev)
{
int ret;
int i;
/* Set up client devices for each base application */
for (i = 0; i < ARRAY_SIZE(qcom_qseecom_apps); i++) {
ret = qseecom_client_register(qseecom_dev, &qcom_qseecom_apps[i]);
if (ret)
return ret;
}
return 0;
}
static struct platform_driver qcom_qseecom_driver = {
.driver = {
.name = "qcom_qseecom",
},
.probe = qcom_qseecom_probe,
};
static int __init qcom_qseecom_init(void)
{
return platform_driver_register(&qcom_qseecom_driver);
}
subsys_initcall(qcom_qseecom_init);
MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
MODULE_DESCRIPTION("Driver for the Qualcomm SEE (QSEECOM) interface");
MODULE_LICENSE("GPL");
This diff is collapsed.
This diff is collapsed.
......@@ -117,6 +117,12 @@ static const char *const pmic_models[] = {
[55] = "PM2250",
[58] = "PM8450",
[65] = "PM8010",
[69] = "PM8550VS",
[70] = "PM8550VE",
[71] = "PM8550B",
[72] = "PMR735D",
[73] = "PM8550",
[74] = "PMK8550",
};
struct socinfo_params {
......@@ -349,6 +355,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SDA439) },
{ qcom_board_id(SDA429) },
{ qcom_board_id(SM7150) },
{ qcom_board_id(SM7150P) },
{ qcom_board_id(IPQ8070) },
{ qcom_board_id(IPQ8071) },
{ qcom_board_id(QM215) },
......@@ -359,6 +366,9 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SM6125) },
{ qcom_board_id(IPQ8070A) },
{ qcom_board_id(IPQ8071A) },
{ qcom_board_id(IPQ8172) },
{ qcom_board_id(IPQ8173) },
{ qcom_board_id(IPQ8174) },
{ qcom_board_id(IPQ6018) },
{ qcom_board_id(IPQ6028) },
{ qcom_board_id(SDM429W) },
......@@ -389,6 +399,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id_named(SM8450_3, "SM8450") },
{ qcom_board_id(SC7280) },
{ qcom_board_id(SC7180P) },
{ qcom_board_id(QCM6490) },
{ qcom_board_id(IPQ5000) },
{ qcom_board_id(IPQ0509) },
{ qcom_board_id(IPQ0518) },
......
......@@ -355,7 +355,6 @@ static struct rpmsg_driver wcnss_ctrl_driver = {
.callback = wcnss_ctrl_smd_callback,
.drv = {
.name = "qcom_wcnss_ctrl",
.owner = THIS_MODULE,
.of_match_table = wcnss_ctrl_of_match,
},
};
......
......@@ -193,6 +193,7 @@
#define QCOM_ID_SDA439 363
#define QCOM_ID_SDA429 364
#define QCOM_ID_SM7150 365
#define QCOM_ID_SM7150P 366
#define QCOM_ID_IPQ8070 375
#define QCOM_ID_IPQ8071 376
#define QCOM_ID_QM215 386
......@@ -203,6 +204,9 @@
#define QCOM_ID_SM6125 394
#define QCOM_ID_IPQ8070A 395
#define QCOM_ID_IPQ8071A 396
#define QCOM_ID_IPQ8172 397
#define QCOM_ID_IPQ8173 398
#define QCOM_ID_IPQ8174 399
#define QCOM_ID_IPQ6018 402
#define QCOM_ID_IPQ6028 403
#define QCOM_ID_SDM429W 416
......@@ -233,6 +237,7 @@
#define QCOM_ID_SM8450_3 482
#define QCOM_ID_SC7280 487
#define QCOM_ID_SC7180P 495
#define QCOM_ID_QCM6490 497
#define QCOM_ID_IPQ5000 503
#define QCOM_ID_IPQ0509 504
#define QCOM_ID_IPQ0518 505
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Driver for Qualcomm Secure Execution Environment (SEE) interface (QSEECOM).
* Responsible for setting up and managing QSEECOM client devices.
*
* Copyright (C) 2023 Maximilian Luz <luzmaximilian@gmail.com>
*/
#include <linux/auxiliary_bus.h>
#include <linux/types.h>
#include <linux/firmware/qcom/qcom_scm.h>
/**
* struct qseecom_client - QSEECOM client device.
* @aux_dev: Underlying auxiliary device.
* @app_id: ID of the loaded application.
*/
struct qseecom_client {
struct auxiliary_device aux_dev;
u32 app_id;
};
/**
* qcom_qseecom_app_send() - Send to and receive data from a given QSEE app.
* @client: The QSEECOM client associated with the target app.
* @req: Request buffer sent to the app (must be DMA-mappable).
* @req_size: Size of the request buffer.
* @rsp: Response buffer, written to by the app (must be DMA-mappable).
* @rsp_size: Size of the response buffer.
*
* Sends a request to the QSEE app associated with the given client and read
* back its response. The caller must provide two DMA memory regions, one for
* the request and one for the response, and fill out the @req region with the
* respective (app-specific) request data. The QSEE app reads this and returns
* its response in the @rsp region.
*
* Note: This is a convenience wrapper around qcom_scm_qseecom_app_send().
* Clients should prefer to use this wrapper.
*
* Return: Zero on success, nonzero on failure.
*/
static inline int qcom_qseecom_app_send(struct qseecom_client *client, void *req, size_t req_size,
void *rsp, size_t rsp_size)
{
return qcom_scm_qseecom_app_send(client->app_id, req, req_size, rsp, rsp_size);
}
......@@ -122,4 +122,26 @@ extern int qcom_scm_lmh_dcvsh(u32 payload_fn, u32 payload_reg, u32 payload_val,
extern int qcom_scm_lmh_profile_change(u32 profile_id);
extern bool qcom_scm_lmh_dcvsh_available(void);
#ifdef CONFIG_QCOM_QSEECOM
int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id);
int qcom_scm_qseecom_app_send(u32 app_id, void *req, size_t req_size, void *rsp,
size_t rsp_size);
#else /* CONFIG_QCOM_QSEECOM */
static inline int qcom_scm_qseecom_app_get_id(const char *app_name, u32 *app_id)
{
return -EINVAL;
}
static inline int qcom_scm_qseecom_app_send(u32 app_id, void *req,
size_t req_size, void *rsp,
size_t rsp_size)
{
return -EINVAL;
}
#endif /* CONFIG_QCOM_QSEECOM */
#endif
......@@ -10,6 +10,7 @@ typedef u16 ucs2_char_t;
unsigned long ucs2_strnlen(const ucs2_char_t *s, size_t maxlength);
unsigned long ucs2_strlen(const ucs2_char_t *s);
unsigned long ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength);
ssize_t ucs2_strscpy(ucs2_char_t *dst, const ucs2_char_t *src, size_t count);
int ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len);
unsigned long ucs2_utf8size(const ucs2_char_t *src);
......
......@@ -32,6 +32,58 @@ ucs2_strsize(const ucs2_char_t *data, unsigned long maxlength)
}
EXPORT_SYMBOL(ucs2_strsize);
/**
* ucs2_strscpy() - Copy a UCS2 string into a sized buffer.
*
* @dst: Pointer to the destination buffer where to copy the string to.
* @src: Pointer to the source buffer where to copy the string from.
* @count: Size of the destination buffer, in UCS2 (16-bit) characters.
*
* Like strscpy(), only for UCS2 strings.
*
* Copy the source string @src, or as much of it as fits, into the destination
* buffer @dst. The behavior is undefined if the string buffers overlap. The
* destination buffer @dst is always NUL-terminated, unless it's zero-sized.
*
* Return: The number of characters copied into @dst (excluding the trailing
* %NUL terminator) or -E2BIG if @count is 0 or @src was truncated due to the
* destination buffer being too small.
*/
ssize_t ucs2_strscpy(ucs2_char_t *dst, const ucs2_char_t *src, size_t count)
{
long res;
/*
* Ensure that we have a valid amount of space. We need to store at
* least one NUL-character.
*/
if (count == 0 || WARN_ON_ONCE(count > INT_MAX / sizeof(*dst)))
return -E2BIG;
/*
* Copy at most 'count' characters, return early if we find a
* NUL-terminator.
*/
for (res = 0; res < count; res++) {
ucs2_char_t c;
c = src[res];
dst[res] = c;
if (!c)
return res;
}
/*
* The loop above terminated without finding a NUL-terminator,
* exceeding the 'count': Enforce proper NUL-termination and return
* error.
*/
dst[count - 1] = 0;
return -E2BIG;
}
EXPORT_SYMBOL(ucs2_strscpy);
int
ucs2_strncmp(const ucs2_char_t *a, const ucs2_char_t *b, size_t len)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment