summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-09-15 07:33:01 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-09-15 07:33:00 -0700
commit7ad50395d8fcb9a7cdfa27978279e2f15b299c8c (patch)
treef198f1534924840fd814c003e486ebfd77e27930
parent5aa936716e843c264feae686a97b1d0079cfed70 (diff)
parentfb272b7bd6525294ea0092b6290dd99b8bb573cf (diff)
Merge "defconfig: enable spss-utils driver for msmcobalt"
-rw-r--r--Documentation/devicetree/bindings/arm/msm/spss_utils.txt27
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi10
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig1
-rw-r--r--drivers/soc/qcom/Kconfig11
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/spss_utils.c294
8 files changed, 350 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/spss_utils.txt b/Documentation/devicetree/bindings/arm/msm/spss_utils.txt
new file mode 100644
index 000000000000..21b96377e5e4
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/spss_utils.txt
@@ -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 */
+ };
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index 48a23b44b5b2..7ce95b04a509 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -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",
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index f672aafd480a..d63d1f429803 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -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>;
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 5d76e41d4fed..c425514ddec5 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -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
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 367822dd0a94..27f7ac6663d6 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -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
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index f884f829b51c..9c27344165be 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -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"
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index fb8437d7a7c3..d9134a558be6 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -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
diff --git a/drivers/soc/qcom/spss_utils.c b/drivers/soc/qcom/spss_utils.c
new file mode 100644
index 000000000000..9f799dfd9003
--- /dev/null
+++ b/drivers/soc/qcom/spss_utils.c
@@ -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");