lede/target/linux/ipq806x/patches-4.9/312-firmware-qcom-scm-fuse-access.patch
2017-09-06 19:19:45 +08:00

99 lines
2.5 KiB
Diff

--- a/drivers/firmware/qcom_scm-32.c
+++ b/drivers/firmware/qcom_scm-32.c
@@ -578,3 +578,33 @@ int __qcom_scm_pinmux_write(u32 svc_id,
return ret;
}
+
+int __qcom_scm_fuse(struct device *dev, u32 address, u32 *val)
+{
+ __le32 *otp_value;
+ dma_addr_t in;
+ int ret;
+
+ otp_value = kzalloc(PAGE_ALIGN(sizeof(*otp_value)), GFP_KERNEL);
+ if (!otp_value)
+ return -ENOMEM;
+
+ in = dma_map_single(dev, otp_value, sizeof(in), DMA_FROM_DEVICE);
+
+ ret = dma_mapping_error(dev, in);
+ if (ret != 0) {
+ kfree(otp_value);
+ pr_err("DMA Mapping Error %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_scm_call(dev, QCOM_SCM_SVC_FUSE, address,
+ &in, sizeof(in), NULL, 0);
+
+ dma_unmap_single(dev, in, sizeof(in), DMA_FROM_DEVICE);
+
+ *val = le32_to_cpu(*otp_value);
+ kfree(otp_value);
+
+ return ret;
+}
--- a/drivers/firmware/qcom_scm.c
+++ b/drivers/firmware/qcom_scm.c
@@ -165,6 +165,25 @@ int qcom_scm_hdcp_req(struct qcom_scm_hd
EXPORT_SYMBOL(qcom_scm_hdcp_req);
/**
+ * qcom_scm_fuse() - Reads a value from the OTP
+ * @address: address
+ *
+ * Returns the value of the OTP at the specified address.
+ */
+int qcom_scm_fuse(u32 address, u32 *val)
+{
+ int ret = qcom_scm_clk_enable();
+
+ if (ret)
+ return ret;
+
+ ret = __qcom_scm_fuse(__scm->dev, address, val);
+ qcom_scm_clk_disable();
+ return ret;
+}
+EXPORT_SYMBOL(qcom_scm_fuse);
+
+/**
* qcom_scm_pas_supported() - Check if the peripheral authentication service is
* available for the given peripherial
* @peripheral: peripheral id
--- a/drivers/firmware/qcom_scm.h
+++ b/drivers/firmware/qcom_scm.h
@@ -63,6 +63,9 @@ extern int __qcom_scm_pas_mss_reset(str
s32 __qcom_scm_pinmux_read(u32 svc_id, u32 cmd_id, u32 arg1);
s32 __qcom_scm_pinmux_write(u32 svc_id, u32 cmd_id, u32 arg1, u32 arg2);
+#define QCOM_SCM_SVC_FUSE 0x8
+extern int __qcom_scm_fuse(struct device *dev, u32 address, u32 *val);
+
/* common error codes */
#define QCOM_SCM_V2_EBUSY -12
#define QCOM_SCM_ENOMEM -5
--- a/include/linux/qcom_scm.h
+++ b/include/linux/qcom_scm.h
@@ -48,4 +48,7 @@ extern u32 qcom_scm_get_version(void);
extern s32 qcom_scm_pinmux_read(u32 arg1);
extern s32 qcom_scm_pinmux_write(u32 arg1, u32 arg2);
+
+extern int qcom_scm_fuse(u32 address, u32 *val);
+
#endif
--- a/drivers/firmware/qcom_scm-64.c
+++ b/drivers/firmware/qcom_scm-64.c
@@ -374,3 +374,9 @@ int __qcom_scm_pinmux_write(u32 svc_id,
{
return -ENOTSUPP;
}
+
+int __qcom_scm_fuse(struct device *dev, u32 address, u32 *val)
+{
+ *val = -1;
+ return -ENOTSUPP;
+}