diff options
| author | Shashank Mittal <mittals@codeaurora.org> | 2015-06-23 17:11:22 -0700 |
|---|---|---|
| committer | Jeevan Shriram <jshriram@codeaurora.org> | 2016-05-16 20:10:40 -0700 |
| commit | 8f4e416b1ece1ccdb52e511a2cb2b692e517736e (patch) | |
| tree | 555df8ac5188f5d37ef347b910747553f79d17a4 | |
| parent | 4e0b31c437eebf94bd06204d13c1c41eec1baac6 (diff) | |
soc: qcom: dcc: add support for DCC XPU lock/unlock request
Add support to request TZ to lock and unlock DCC XPU.
DCC XPU is unlocked before accessing DCC and is locked back again after
configuring DCC.
Change-Id: I8815f65551df0b80f7ecdcaa338a50db8d9b04f5
Signed-off-by: Shashank Mittal <mittals@codeaurora.org>
| -rw-r--r-- | Documentation/devicetree/bindings/soc/qcom/dcc.txt | 7 | ||||
| -rw-r--r-- | drivers/soc/qcom/dcc.c | 159 |
2 files changed, 155 insertions, 11 deletions
diff --git a/Documentation/devicetree/bindings/soc/qcom/dcc.txt b/Documentation/devicetree/bindings/soc/qcom/dcc.txt index d1ffc6830875..53ac911d182e 100644 --- a/Documentation/devicetree/bindings/soc/qcom/dcc.txt +++ b/Documentation/devicetree/bindings/soc/qcom/dcc.txt @@ -10,7 +10,7 @@ Required properties: - compatible : name of the component used for driver matching, should be "qcom,dcc" -- reg : physical base address and length of the register set(s) and SRAM +- reg : physical base address and length of the register set(s), SRAM and XPU of the component. - reg-names : names corresponding to each reg property value. @@ -30,8 +30,9 @@ Example: dcc: dcc@4b3000 { compatible = "qcom,dcc"; reg = <0x4b3000 0x1000>, - <0x4b4000 0x2000>; - reg-names = "dcc-base", "dcc-ram-base"; + <0x4b4000 0x2000>, + <0x4b0000 0x1>; + reg-names = "dcc-base", "dcc-ram-base", "dcc-xpu-base"; clocks = <&clock_gcc clk_gcc_dcc_ahb_clk>; clock-names = "dcc_clk"; diff --git a/drivers/soc/qcom/dcc.c b/drivers/soc/qcom/dcc.c index 6b171b31e301..6ec796e98be9 100644 --- a/drivers/soc/qcom/dcc.c +++ b/drivers/soc/qcom/dcc.c @@ -23,6 +23,7 @@ #include <linux/uaccess.h> #include <soc/qcom/memory_dump.h> #include <soc/qcom/rpm-smd.h> +#include <soc/qcom/scm.h> #define RPM_MISC_REQ_TYPE 0x6373696d #define RPM_MISC_DDR_DCC_ENABLE 0x32726464 @@ -64,6 +65,8 @@ #define MAX_DCC_OFFSET (0xFF * 4) #define MAX_DCC_LEN 0x7F +#define SCM_SVC_DISABLE_XPU 0x23 + enum dcc_func_type { DCC_FUNC_TYPE_CAPTURE, DCC_FUNC_TYPE_CRC, @@ -122,8 +125,82 @@ struct dcc_drvdata { struct msm_dump_data sram_data; struct rpm_trig_req rpm_trig_req; struct msm_rpm_kvp rpm_kvp; + bool xpu_scm_avail; + uint64_t xpu_addr; + uint32_t xpu_unlock_count; }; +static int dcc_cfg_xpu(struct dcc_drvdata *drvdata, bool enable) +{ + struct scm_desc desc = {0}; + + desc.args[0] = drvdata->xpu_addr; + desc.args[1] = enable; + desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL); + + return scm_call2(SCM_SIP_FNID(SCM_SVC_MP, SCM_SVC_DISABLE_XPU), &desc); +} + +static int dcc_xpu_lock(struct dcc_drvdata *drvdata) +{ + int ret = 0; + + mutex_lock(&drvdata->mutex); + if (!drvdata->xpu_scm_avail) + goto err; + + if (drvdata->xpu_unlock_count == 0) + goto err; + + if (drvdata->xpu_unlock_count == 1) { + ret = clk_prepare_enable(drvdata->clk); + if (ret) + goto err; + + /* make sure all access to DCC are completed */ + mb(); + + ret = dcc_cfg_xpu(drvdata, 1); + if (ret) + dev_err(drvdata->dev, "Falied to lock DCC XPU.\n"); + + clk_disable_unprepare(drvdata->clk); + } + + if (!ret) + drvdata->xpu_unlock_count--; +err: + mutex_unlock(&drvdata->mutex); + return ret; +} + +static int dcc_xpu_unlock(struct dcc_drvdata *drvdata) +{ + int ret = 0; + + mutex_lock(&drvdata->mutex); + if (!drvdata->xpu_scm_avail) + goto err; + + if (drvdata->xpu_unlock_count == 0) { + ret = clk_prepare_enable(drvdata->clk); + if (ret) + goto err; + + ret = dcc_cfg_xpu(drvdata, 0); + if (ret) + dev_err(drvdata->dev, "Falied to unlock DCC XPU.\n"); + + clk_disable_unprepare(drvdata->clk); + } + + if (!ret) + drvdata->xpu_unlock_count++; +err: + mutex_unlock(&drvdata->mutex); + return ret; +} + static bool dcc_ready(struct dcc_drvdata *drvdata) { uint32_t val; @@ -542,11 +619,16 @@ static ssize_t dcc_store_trigger(struct device *dev, if (val != 1) return -EINVAL; - ret = dcc_sw_trigger(drvdata); + ret = dcc_xpu_unlock(drvdata); if (ret) return ret; - return size; + ret = dcc_sw_trigger(drvdata); + if (!ret) + ret = size; + + dcc_xpu_lock(drvdata); + return ret; } static DEVICE_ATTR(trigger, S_IWUSR, NULL, dcc_store_trigger); @@ -570,14 +652,20 @@ static ssize_t dcc_store_enable(struct device *dev, if (kstrtoul(buf, 16, &val)) return -EINVAL; + ret = dcc_xpu_unlock(drvdata); + if (ret) + return ret; + if (val) ret = dcc_enable(drvdata); else dcc_disable(drvdata); - if (ret) - return ret; - return size; + if (!ret) + ret = size; + + dcc_xpu_lock(drvdata); + return ret; } static DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, dcc_show_enable, @@ -764,6 +852,10 @@ static ssize_t dcc_show_crc_error(struct device *dev, int ret; struct dcc_drvdata *drvdata = dev_get_drvdata(dev); + ret = dcc_xpu_unlock(drvdata); + if (ret) + return ret; + mutex_lock(&drvdata->mutex); if (!drvdata->enable) { ret = -EINVAL; @@ -774,6 +866,7 @@ static ssize_t dcc_show_crc_error(struct device *dev, (unsigned)BVAL(dcc_readl(drvdata, DCC_STATUS), 0)); err: mutex_unlock(&drvdata->mutex); + dcc_xpu_lock(drvdata); return ret; } static DEVICE_ATTR(crc_error, S_IRUGO, dcc_show_crc_error, NULL); @@ -784,6 +877,10 @@ static ssize_t dcc_show_ready(struct device *dev, int ret; struct dcc_drvdata *drvdata = dev_get_drvdata(dev); + ret = dcc_xpu_unlock(drvdata); + if (ret) + return ret; + mutex_lock(&drvdata->mutex); if (!drvdata->enable) { ret = -EINVAL; @@ -794,6 +891,7 @@ static ssize_t dcc_show_ready(struct device *dev, (unsigned)BVAL(dcc_readl(drvdata, DCC_STATUS), 4)); err: mutex_unlock(&drvdata->mutex); + dcc_xpu_lock(drvdata); return ret; } static DEVICE_ATTR(ready, S_IRUGO, dcc_show_ready, NULL); @@ -854,6 +952,25 @@ static ssize_t dcc_store_rpm_sw_trigger_on(struct device *dev, static DEVICE_ATTR(rpm_sw_trigger_on, S_IRUGO | S_IWUSR, dcc_show_rpm_sw_trigger_on, dcc_store_rpm_sw_trigger_on); +static ssize_t dcc_store_xpu_unlock(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + int ret; + unsigned long val; + struct dcc_drvdata *drvdata = dev_get_drvdata(dev); + + if (kstrtoul(buf, 10, &val)) + return -EINVAL; + + ret = val ? dcc_xpu_unlock(drvdata) : dcc_xpu_lock(drvdata); + if (!ret) + ret = size; + + return ret; +} +static DEVICE_ATTR(xpu_unlock, S_IWUSR, NULL, dcc_store_xpu_unlock); + static const struct device_attribute *dcc_attrs[] = { &dev_attr_func_type, &dev_attr_data_sink, @@ -865,6 +982,7 @@ static const struct device_attribute *dcc_attrs[] = { &dev_attr_crc_error, &dev_attr_interrupt_disable, &dev_attr_rpm_sw_trigger_on, + &dev_attr_xpu_unlock, NULL, }; @@ -890,7 +1008,8 @@ static int dcc_sram_open(struct inode *inode, struct file *file) struct dcc_drvdata, sram_dev); file->private_data = drvdata; - return 0; + + return dcc_xpu_unlock(drvdata); } static ssize_t dcc_sram_read(struct file *file, char __user *data, @@ -937,7 +1056,9 @@ static ssize_t dcc_sram_read(struct file *file, char __user *data, static int dcc_sram_release(struct inode *inode, struct file *file) { - return 0; + struct dcc_drvdata *drvdata = file->private_data; + + return dcc_xpu_lock(drvdata); } static const struct file_operations dcc_sram_fops = { @@ -1114,12 +1235,34 @@ static int dcc_probe(struct platform_device *pdev) INIT_LIST_HEAD(&drvdata->config_head); drvdata->nr_config = 0; - ret = clk_prepare_enable(drvdata->clk); + if (scm_is_call_available(SCM_SVC_MP, SCM_SVC_DISABLE_XPU) > 0) + drvdata->xpu_scm_avail = 1; + else + drvdata->xpu_scm_avail = 0; + + if (drvdata->xpu_scm_avail) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "dcc-xpu-base"); + if (!res) + return -ENODEV; + + drvdata->xpu_addr = res->start; + } + + ret = dcc_xpu_unlock(drvdata); if (ret) goto err; + ret = clk_prepare_enable(drvdata->clk); + if (ret) { + dcc_xpu_lock(drvdata); + goto err; + } + memset_io(drvdata->ram_base, 0, drvdata->ram_size); + dcc_xpu_lock(drvdata); + clk_disable_unprepare(drvdata->clk); drvdata->data_sink = DCC_DATA_SINK_SRAM; |
