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-fuse1-addr: fuse1 register physical address
+-qcom,spss-fuse1-bit: fuse1 relevant bit
+-qcom,spss-fuse2-addr: fuse2 register physical address
+-qcom,spss-fuse2-bit: fuse2 relevant bit
-qcom,spss-test-firmware-name: test firmware file name
-qcom,spss-prod-firmware-name: production firmware file name
+-qcom,spss-hybr-firmware-name: hybrid firmware file name
-qcom,spss-debug-reg-addr: debug register physical address
Example:
qcom,spss_utils {
compatible = "qcom,spss-utils";
- qcom,spss-fuse-addr = <0x007841c4>; /* 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 */
+ qcom,spss-fuse1-addr = <0x007841c4>;
+ qcom,spss-fuse1-bit = <27>;
+ qcom,spss-fuse2-addr = <0x0078413c>;
+ qcom,spss-fuse2-bit = <31>;
+ qcom,spss-test-firmware-name = "spss2t"; /* 8 chars max */
+ qcom,spss-prod-firmware-name = "spss2p"; /* 8 chars max */
+ qcom,spss-hybr-firmware-name = "spss2h"; /* 8 chars max */
qcom,spss-debug-reg-addr = <0x01d06020>;
};
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, 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
*
* The SP daemon needs to load different SPSS images based on:
*
- * 1. Test/Production key used to sign the SPSS image (read fuse).
+ * 1. Test/Production key used to sign the SPSS image (read fuses).
* 2. SPSS HW version (selected via Device Tree).
*
*/
/* driver name */
#define DEVICE_NAME "spss-utils"
-static bool is_test_fuse_set;
+enum spss_firmware_type {
+ SPSS_FW_TYPE_TEST = 't',
+ SPSS_FW_TYPE_PROD = 'p',
+ SPSS_FW_TYPE_HYBRID = 'h',
+};
+
+static enum spss_firmware_type firmware_type = SPSS_FW_TYPE_TEST;
static const char *test_firmware_name;
static const char *prod_firmware_name;
-static const char *firmware_name;
+static const char *hybr_firmware_name;
+static const char *firmware_name = "NA";
static struct device *spss_dev;
static u32 spss_debug_reg_addr; /* SP_SCSR_MBn_SP2CL_GPm(n,m) */
return -EINVAL;
}
- if (is_test_fuse_set)
+ switch (firmware_type) {
+ case SPSS_FW_TYPE_TEST:
ret = snprintf(buf, PAGE_SIZE, "%s", "test");
- else
+ break;
+ case SPSS_FW_TYPE_PROD:
ret = snprintf(buf, PAGE_SIZE, "%s", "prod");
+ break;
+ case SPSS_FW_TYPE_HYBRID:
+ ret = snprintf(buf, PAGE_SIZE, "%s", "hybrid");
+ break;
+ default:
+ return -EINVAL;
+ }
return ret;
}
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;
+ u32 spss_fuse1_addr = 0;
+ u32 spss_fuse1_bit = 0;
+ u32 spss_fuse1_mask = 0;
+ void __iomem *spss_fuse1_reg = NULL;
+ u32 spss_fuse2_addr = 0;
+ u32 spss_fuse2_bit = 0;
+ u32 spss_fuse2_mask = 0;
+ void __iomem *spss_fuse2_reg = NULL;
+ u32 val1 = 0;
+ u32 val2 = 0;
ret = of_property_read_string(node, "qcom,spss-test-firmware-name",
&test_firmware_name);
return -EFAULT;
}
- ret = of_property_read_u32(node, "qcom,spss-fuse-addr",
- &spss_fuse_addr);
+ ret = of_property_read_string(node, "qcom,spss-hybr-firmware-name",
+ &hybr_firmware_name);
+ if (ret < 0) {
+ pr_err("can't get prod fw name.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,spss-fuse1-addr",
+ &spss_fuse1_addr);
+ if (ret < 0) {
+ pr_err("can't get fuse1 addr.\n");
+ return -EFAULT;
+ }
+
+ ret = of_property_read_u32(node, "qcom,spss-fuse2-addr",
+ &spss_fuse2_addr);
if (ret < 0) {
- pr_err("can't get fuse addr.\n");
+ pr_err("can't get fuse2 addr.\n");
return -EFAULT;
}
- ret = of_property_read_u32(node, "qcom,spss-fuse-bit",
- &spss_fuse_bit);
+ ret = of_property_read_u32(node, "qcom,spss-fuse1-bit",
+ &spss_fuse1_bit);
if (ret < 0) {
- pr_err("can't get fuse bit.\n");
+ pr_err("can't get fuse1 bit.\n");
return -EFAULT;
}
- spss_fuse_mask = BIT(spss_fuse_bit);
+ ret = of_property_read_u32(node, "qcom,spss-fuse2-bit",
+ &spss_fuse2_bit);
+ if (ret < 0) {
+ pr_err("can't get fuse2 bit.\n");
+ return -EFAULT;
+ }
- 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));
+ spss_fuse1_mask = BIT(spss_fuse1_bit);
+ spss_fuse2_mask = BIT(spss_fuse2_bit);
- if (!spss_fuse_reg) {
- pr_err("can't map fuse addr.\n");
+ pr_debug("spss fuse1 addr [0x%x] bit [%d] .\n",
+ (int) spss_fuse1_addr, (int) spss_fuse1_bit);
+ pr_debug("spss fuse2 addr [0x%x] bit [%d] .\n",
+ (int) spss_fuse2_addr, (int) spss_fuse2_bit);
+
+ spss_fuse1_reg = ioremap_nocache(spss_fuse1_addr, sizeof(u32));
+ spss_fuse2_reg = ioremap_nocache(spss_fuse2_addr, sizeof(u32));
+
+ if (!spss_fuse1_reg) {
+ pr_err("can't map fuse1 addr.\n");
return -EFAULT;
}
+ if (!spss_fuse2_reg) {
+ pr_err("can't map fuse2 addr.\n");
+ return -EFAULT;
+ }
+
+ val1 = readl_relaxed(spss_fuse1_reg);
+ val2 = readl_relaxed(spss_fuse2_reg);
- val = readl_relaxed(spss_fuse_reg);
+ pr_debug("spss fuse1 value [0x%08x].\n", (int) val1);
+ pr_debug("spss fuse2 value [0x%08x].\n", (int) val2);
- pr_debug("spss fuse register value [0x%x].\n", (int) val);
+ pr_debug("spss fuse1 mask [0x%08x].\n", (int) spss_fuse1_mask);
+ pr_debug("spss fuse2 mask [0x%08x].\n", (int) spss_fuse2_mask);
- if (val & spss_fuse_mask)
- is_test_fuse_set = true;
+ if (val1 & spss_fuse1_mask)
+ firmware_type = SPSS_FW_TYPE_TEST;
+ else if (val2 & spss_fuse2_mask)
+ firmware_type = SPSS_FW_TYPE_PROD;
+ else
+ firmware_type = SPSS_FW_TYPE_HYBRID;
- iounmap(spss_fuse_reg);
+ iounmap(spss_fuse1_reg);
+ iounmap(spss_fuse2_reg);
ret = of_property_read_u32(node, "qcom,spss-debug-reg-addr",
&spss_debug_reg_addr);
return -EFAULT;
}
- if (is_test_fuse_set)
+ switch (firmware_type) {
+ case SPSS_FW_TYPE_TEST:
firmware_name = test_firmware_name;
- else
+ break;
+ case SPSS_FW_TYPE_PROD:
firmware_name = prod_firmware_name;
+ break;
+ case SPSS_FW_TYPE_HYBRID:
+ firmware_name = hybr_firmware_name;
+ break;
+ default:
+ return -EINVAL;
+ }
ret = subsystem_set_fwname("spss", firmware_name);
if (ret < 0) {
{
int ret = 0;
- pr_info("spss-utils driver Ver 1.1 18-Sep-2016.\n");
+ pr_info("spss-utils driver Ver 1.2 13-Jan-2017.\n");
ret = platform_driver_register(&spss_driver);
if (ret)