Merge "defconfig: enable spss-utils driver for msmcobalt"
This commit is contained in:
commit
7ad50395d8
8 changed files with 350 additions and 0 deletions
27
Documentation/devicetree/bindings/arm/msm/spss_utils.txt
Normal file
27
Documentation/devicetree/bindings/arm/msm/spss_utils.txt
Normal file
|
@ -0,0 +1,27 @@
|
|||
Qualcomm Technologies, Inc. Secure Processor SubSystem Utilities (spss_utils)
|
||||
|
||||
The Secure Processor SubSystem (SPSS) is a dedicated subsystem for security.
|
||||
It has its own CPU, memories, and cryptographic engine.
|
||||
It shall provide cryptographic services to other subsystems.
|
||||
The SPSS firmware is loaded by PIL driver.
|
||||
The communication with SPSS is done via spcom driver, using glink.
|
||||
|
||||
The spss_utils driver selects the SPSS firmware file,
|
||||
according to a dedicated fuse and the platform HW version.
|
||||
|
||||
Required properties:
|
||||
-compatible : should be "qcom,spss_utils"
|
||||
-qcom,spss-fuse-addr: fuse register physical address
|
||||
-qcom,spss-fuse-bit: fuse relevant bit
|
||||
-qcom,spss-test-firmware-name: test firmware file name
|
||||
-qcom,spss-prod-firmware-name: production firmware file name
|
||||
|
||||
Example:
|
||||
qcom,spss_utils {
|
||||
compatible = "qcom,spss-utils";
|
||||
|
||||
qcom,spss-fuse-addr = <0x007841c4 0x4>; /* spss test fuse physical address */
|
||||
qcom,spss-fuse-bit = <27>;
|
||||
qcom,spss-test-firmware-name = "spss1t"; /* 8 chars max */
|
||||
qcom,spss-prod-firmware-name = "spss1p"; /* 8 chars max */
|
||||
};
|
|
@ -746,6 +746,11 @@
|
|||
};
|
||||
};
|
||||
|
||||
&spss_utils {
|
||||
qcom,spss-test-firmware-name = "spss2t"; /* 8 chars max */
|
||||
qcom,spss-prod-firmware-name = "spss2p"; /* 8 chars max */
|
||||
};
|
||||
|
||||
&ufs1 {
|
||||
clock-names =
|
||||
"core_clk",
|
||||
|
|
|
@ -1635,6 +1635,16 @@
|
|||
status = "ok";
|
||||
};
|
||||
|
||||
spss_utils: qcom,spss_utils {
|
||||
compatible = "qcom,spss-utils";
|
||||
/* spss test fuse physical address */
|
||||
qcom,spss-fuse-addr = <0x007841c4 0x4>;
|
||||
qcom,spss-fuse-bit = <27>;
|
||||
qcom,spss-test-firmware-name = "spss"; /* default name */
|
||||
qcom,spss-prod-firmware-name = "spss1p"; /* 8 chars max */
|
||||
status = "ok";
|
||||
};
|
||||
|
||||
sdhc_2: sdhci@c0a4900 {
|
||||
compatible = "qcom,sdhci-msm";
|
||||
reg = <0xc0a4900 0x314>, <0xc0a4000 0x800>;
|
||||
|
|
|
@ -494,6 +494,7 @@ CONFIG_MSM_GLINK_SMD_XPRT=y
|
|||
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
|
||||
CONFIG_MSM_GLINK_SPI_XPRT=y
|
||||
CONFIG_MSM_SPCOM=y
|
||||
CONFIG_MSM_SPSS_UTILS=y
|
||||
CONFIG_MSM_SMEM_LOGGING=y
|
||||
CONFIG_MSM_SMP2P=y
|
||||
CONFIG_MSM_SMP2P_TEST=y
|
||||
|
|
|
@ -506,6 +506,7 @@ CONFIG_MSM_GLINK_SMD_XPRT=y
|
|||
CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
|
||||
CONFIG_MSM_GLINK_SPI_XPRT=y
|
||||
CONFIG_MSM_SPCOM=y
|
||||
CONFIG_MSM_SPSS_UTILS=y
|
||||
CONFIG_MSM_SMEM_LOGGING=y
|
||||
CONFIG_MSM_SMP2P=y
|
||||
CONFIG_MSM_SMP2P_TEST=y
|
||||
|
|
|
@ -127,6 +127,17 @@ config MSM_SPCOM
|
|||
spcom provides clients/server API, although currently only one client
|
||||
or server is allowed per logical channel.
|
||||
|
||||
config MSM_SPSS_UTILS
|
||||
depends on MSM_PIL
|
||||
bool "Secure Processor Utilities"
|
||||
help
|
||||
spss-utils driver selects Secure Processor firmware file name.
|
||||
The firmware file name for test or production is selected based
|
||||
on a test fuse.
|
||||
Different file name is used for differnt SPSS HW versions,
|
||||
because the SPSS firmware size is too small to support multiple
|
||||
HW versions.
|
||||
|
||||
config MSM_SMEM_LOGGING
|
||||
depends on MSM_SMEM
|
||||
bool "MSM Shared Memory Logger"
|
||||
|
|
|
@ -28,6 +28,7 @@ obj-$(CONFIG_MSM_IPC_ROUTER_HSIC_XPRT) += ipc_router_hsic_xprt.o
|
|||
obj-$(CONFIG_MSM_IPC_ROUTER_MHI_XPRT) += ipc_router_mhi_xprt.o
|
||||
obj-$(CONFIG_MSM_IPC_ROUTER_GLINK_XPRT) += ipc_router_glink_xprt.o
|
||||
obj-$(CONFIG_MSM_SPCOM) += spcom.o
|
||||
obj-$(CONFIG_MSM_SPSS_UTILS) += spss_utils.o
|
||||
obj-y += qdsp6v2/
|
||||
obj-$(CONFIG_MSM_SYSTEM_HEALTH_MONITOR) += system_health_monitor_v01.o
|
||||
obj-$(CONFIG_MSM_SYSTEM_HEALTH_MONITOR) += system_health_monitor.o
|
||||
|
|
294
drivers/soc/qcom/spss_utils.c
Normal file
294
drivers/soc/qcom/spss_utils.c
Normal file
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
* only version 2 as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Secure-Processor-SubSystem (SPSS) utilities.
|
||||
*
|
||||
* This driver provides utilities for the Secure Processor (SP).
|
||||
*
|
||||
* The SP daemon needs to load different SPSS images based on:
|
||||
*
|
||||
* 1. Test/Production key used to sign the SPSS image (read fuse).
|
||||
* 2. SPSS HW version (selected via Device Tree).
|
||||
*
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "spss_utils [%s]: " fmt, __func__
|
||||
|
||||
#include <linux/kernel.h> /* min() */
|
||||
#include <linux/module.h> /* MODULE_LICENSE */
|
||||
#include <linux/device.h> /* class_create() */
|
||||
#include <linux/slab.h> /* kzalloc() */
|
||||
#include <linux/fs.h> /* file_operations */
|
||||
#include <linux/cdev.h> /* cdev_add() */
|
||||
#include <linux/errno.h> /* EINVAL, ETIMEDOUT */
|
||||
#include <linux/printk.h> /* pr_err() */
|
||||
#include <linux/bitops.h> /* BIT(x) */
|
||||
#include <linux/platform_device.h> /* platform_driver_register() */
|
||||
#include <linux/of.h> /* of_property_count_strings() */
|
||||
#include <linux/io.h> /* ioremap_nocache() */
|
||||
|
||||
#include <soc/qcom/subsystem_restart.h>
|
||||
|
||||
/* driver name */
|
||||
#define DEVICE_NAME "spss-utils"
|
||||
|
||||
static bool is_test_fuse_set;
|
||||
static const char *test_firmware_name;
|
||||
static const char *prod_firmware_name;
|
||||
static const char *firmware_name;
|
||||
static struct device *spss_dev;
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Device Sysfs */
|
||||
/*==========================================================================*/
|
||||
|
||||
static ssize_t firmware_name_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev || !attr || !buf) {
|
||||
pr_err("invalid param.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (firmware_name == NULL)
|
||||
ret = snprintf(buf, PAGE_SIZE, "%s\n", "unknown");
|
||||
else
|
||||
ret = snprintf(buf, PAGE_SIZE, "%s\n", firmware_name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t firmware_name_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
pr_err("set firmware name is not allowed.\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(firmware_name, 0444,
|
||||
firmware_name_show, firmware_name_store);
|
||||
|
||||
static ssize_t test_fuse_state_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev || !attr || !buf) {
|
||||
pr_err("invalid param.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_test_fuse_set)
|
||||
ret = snprintf(buf, PAGE_SIZE, "%s\n", "test");
|
||||
else
|
||||
ret = snprintf(buf, PAGE_SIZE, "%s\n", "prod");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t test_fuse_state_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf,
|
||||
size_t size)
|
||||
{
|
||||
pr_err("set test fuse state is not allowed.\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(test_fuse_state, 0444,
|
||||
test_fuse_state_show, test_fuse_state_store);
|
||||
|
||||
static int spss_create_sysfs(struct device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = device_create_file(dev, &dev_attr_firmware_name);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to create sysfs file for firmware_name.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = device_create_file(dev, &dev_attr_test_fuse_state);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to create sysfs file for test_fuse_state.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Device Tree */
|
||||
/*==========================================================================*/
|
||||
|
||||
/**
|
||||
* spss_parse_dt() - Parse Device Tree info.
|
||||
*/
|
||||
static int spss_parse_dt(struct device_node *node)
|
||||
{
|
||||
int ret;
|
||||
u32 spss_fuse_addr = 0;
|
||||
u32 spss_fuse_bit = 0;
|
||||
u32 spss_fuse_mask = 0;
|
||||
void __iomem *spss_fuse_reg = NULL;
|
||||
u32 val = 0;
|
||||
|
||||
ret = of_property_read_string(node, "qcom,spss-test-firmware-name",
|
||||
&test_firmware_name);
|
||||
if (ret < 0) {
|
||||
pr_err("can't get test fw name.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = of_property_read_string(node, "qcom,spss-prod-firmware-name",
|
||||
&prod_firmware_name);
|
||||
if (ret < 0) {
|
||||
pr_err("can't get prod fw name.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "qcom,spss-fuse-addr",
|
||||
&spss_fuse_addr);
|
||||
if (ret < 0) {
|
||||
pr_err("can't get fuse addr.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(node, "qcom,spss-fuse-bit",
|
||||
&spss_fuse_bit);
|
||||
if (ret < 0) {
|
||||
pr_err("can't get fuse bit.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spss_fuse_mask = BIT(spss_fuse_bit);
|
||||
|
||||
pr_debug("spss_fuse_addr [0x%x] , spss_fuse_bit [%d] .\n",
|
||||
(int) spss_fuse_addr, (int) spss_fuse_bit);
|
||||
|
||||
spss_fuse_reg = ioremap_nocache(spss_fuse_addr, sizeof(u32));
|
||||
|
||||
if (!spss_fuse_reg) {
|
||||
pr_err("can't map fuse addr.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
val = readl_relaxed(spss_fuse_reg);
|
||||
|
||||
pr_debug("spss fuse register value [0x%x].\n", (int) val);
|
||||
|
||||
if (val & spss_fuse_mask)
|
||||
is_test_fuse_set = true;
|
||||
|
||||
iounmap(spss_fuse_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* spss_probe() - initialization sequence
|
||||
*/
|
||||
static int spss_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device_node *np = NULL;
|
||||
struct device *dev = NULL;
|
||||
|
||||
if (!pdev) {
|
||||
pr_err("invalid pdev.\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
np = pdev->dev.of_node;
|
||||
if (!np) {
|
||||
pr_err("invalid DT node.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev = &pdev->dev;
|
||||
spss_dev = dev;
|
||||
|
||||
if (dev == NULL) {
|
||||
pr_err("invalid dev.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, dev);
|
||||
|
||||
ret = spss_parse_dt(np);
|
||||
if (ret < 0) {
|
||||
pr_err("fail to parse device tree.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (is_test_fuse_set)
|
||||
firmware_name = test_firmware_name;
|
||||
else
|
||||
firmware_name = prod_firmware_name;
|
||||
|
||||
ret = subsystem_set_fwname("spss", firmware_name);
|
||||
if (ret < 0) {
|
||||
pr_err("fail to set fw name.\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
spss_create_sysfs(dev);
|
||||
|
||||
pr_info("Initialization completed ok, firmware_name [%s].\n",
|
||||
firmware_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id spss_match_table[] = {
|
||||
{ .compatible = "qcom,spss-utils", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver spss_driver = {
|
||||
.probe = spss_probe,
|
||||
.driver = {
|
||||
.name = DEVICE_NAME,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = of_match_ptr(spss_match_table),
|
||||
},
|
||||
};
|
||||
|
||||
/*==========================================================================*/
|
||||
/* Driver Init/Exit */
|
||||
/*==========================================================================*/
|
||||
static int __init spss_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pr_info("spss-utils driver Ver 1.0 12-Sep-2016.\n");
|
||||
|
||||
ret = platform_driver_register(&spss_driver);
|
||||
if (ret)
|
||||
pr_err("register platform driver failed, ret [%d]\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(spss_init); /* start after PIL driver */
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("Secure Processor Utilities");
|
Loading…
Add table
Reference in a new issue