From patchwork Mon Jan 26 10:13:28 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 43731 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-we0-f197.google.com (mail-we0-f197.google.com [74.125.82.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 106AB20D5D for ; Mon, 26 Jan 2015 10:13:36 +0000 (UTC) Received: by mail-we0-f197.google.com with SMTP id l61sf3731089wev.0 for ; Mon, 26 Jan 2015 02:13:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=WBdFtaJEqVHDWgSq+0gXDoKKBb9ZIkbSljmMAPe9Q4Y=; b=A/n5HN09Z991LrigDk0McJS9Bomo432LizP7HA07CUpYWpBOphnSyb8c4SChML0zDc 9TXs86lpBxxlh5IKCfwycloRtjGUQ0y2YteZIkehxuePS9TSL44dHvfYNbI7pFUwl7h7 bGAiGHQL5fskGJbotdkdt80ORZO5fAsApNGnIu70+fksYVnM6rPKmF9vMyfk24aKJ2nq P2wo/qkV+qnUuV8PVaDirkDI6jR2IboPwU9J9H3j7trnM9SkDC2XcFRkoMRuaQ2REY1J GdWRzkqe0rnZceyIEuNqIszPsikiPETwaMLO3ibg2Xncabh1DGZ7Av76XnSdl3pnyZ4q 1Oyw== X-Gm-Message-State: ALoCoQnP0VAiLkH61K4jT8NN/Ly/1lBdOd10lLpzC0OUBqwXdaBjTACZ04GpAKt1o9VhtZ34WMOU X-Received: by 10.152.37.130 with SMTP id y2mr1145196laj.8.1422267215368; Mon, 26 Jan 2015 02:13:35 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.153.4.10 with SMTP id ca10ls137686lad.33.gmail; Mon, 26 Jan 2015 02:13:35 -0800 (PST) X-Received: by 10.112.47.135 with SMTP id d7mr20223100lbn.54.1422267215224; Mon, 26 Jan 2015 02:13:35 -0800 (PST) Received: from mail-la0-f48.google.com (mail-la0-f48.google.com. [209.85.215.48]) by mx.google.com with ESMTPS id xw4si8583618lbb.105.2015.01.26.02.13.34 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 26 Jan 2015 02:13:34 -0800 (PST) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.48 as permitted sender) client-ip=209.85.215.48; Received: by mail-la0-f48.google.com with SMTP id pv20so6772598lab.7 for ; Mon, 26 Jan 2015 02:13:34 -0800 (PST) X-Received: by 10.152.44.228 with SMTP id h4mr19283142lam.31.1422267214794; Mon, 26 Jan 2015 02:13:34 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.112.35.133 with SMTP id h5csp729398lbj; Mon, 26 Jan 2015 02:13:34 -0800 (PST) X-Received: by 10.180.205.163 with SMTP id lh3mr31395235wic.63.1422267214019; Mon, 26 Jan 2015 02:13:34 -0800 (PST) Received: from mail-wi0-f174.google.com (mail-wi0-f174.google.com. [209.85.212.174]) by mx.google.com with ESMTPS id s7si18844078wiw.66.2015.01.26.02.13.33 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 26 Jan 2015 02:13:34 -0800 (PST) Received-SPF: pass (google.com: domain of srinivas.kandagatla@linaro.org designates 209.85.212.174 as permitted sender) client-ip=209.85.212.174; Received: by mail-wi0-f174.google.com with SMTP id n3so8775047wiv.1 for ; Mon, 26 Jan 2015 02:13:33 -0800 (PST) X-Received: by 10.194.2.240 with SMTP id 16mr43708590wjx.108.1422267213781; Mon, 26 Jan 2015 02:13:33 -0800 (PST) Received: from srini-ThinkPad-X1-Carbon-2nd.dlink.com (host-2-98-216-248.as13285.net. [2.98.216.248]) by mx.google.com with ESMTPSA id a1sm2962961wjs.40.2015.01.26.02.13.31 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 26 Jan 2015 02:13:33 -0800 (PST) From: Srinivas Kandagatla To: linux-arm-msm@vger.kernel.org Cc: patches@linaro.org, linaro-kernel@lists.linaro.org, Srinivas Kandagatla Subject: [RFC PATCH 2/2] WIP: Add wrappers for qfprom access via syscon Date: Mon, 26 Jan 2015 10:13:28 +0000 Message-Id: <1422267208-6189-1-git-send-email-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1422267151-6034-1-git-send-email-srinivas.kandagatla@linaro.org> References: <1422267151-6034-1-git-send-email-srinivas.kandagatla@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: srinivas.kandagatla@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.48 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Syscon fits very well to access qfprom. This also means drivers which needs to access qfprom have to talk to syscon and get regmap, offset, size and then do regmap reads. This will be kinda redone in every driver. Having a wrapper for this would avoid lot of code duplications and also provide a higher level and user friendly apis for qfprom. This patch attempt to provide such wrappers. This wrappers are easy way to use syscon for qfprom purposes. Advantages of this approch is: - driver need not have hardcoded qfprom offsets or have soc specific compatible strings to determine the offset. - access multiple qfprom resources which is kinda tricky with standard syscon. - no code duplication. - light weight, single call. - not a platform device driver level binding. Signed-off-by: Srinivas Kandagatla --- .../devicetree/bindings/soc/qcom/qfprom.txt | 29 +++++ drivers/soc/qcom/Kconfig | 7 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/qfprom.c | 134 +++++++++++++++++++++ 4 files changed, 171 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/qfprom.txt create mode 100644 drivers/soc/qcom/qfprom.c diff --git a/Documentation/devicetree/bindings/soc/qcom/qfprom.txt b/Documentation/devicetree/bindings/soc/qcom/qfprom.txt new file mode 100644 index 0000000..3ed7309 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qfprom.txt @@ -0,0 +1,29 @@ +QCOM QFPROM + +QFPROM is basically some efuses where things like calibration data, speed bins, +etc are stored. This data is accessed by various drivers like the cpufreq, +thermal, etc. + +Required properties: +- compatible: must contain "qcom,qfprom" followed by "syscon" +- reg: Address range for QFPROM +- stride : register address stride. + 1 for byte. + 2 for 2 bytes + 3 for 3 bytes + 4 for a word. + + +Example: + qfprom: qfprom@00700000 { + compatible = "qcom,qfprom", "syscon"; + reg = <0x00700000 0x1000>; + stride = <1>; + }; + + tsens@34000 { + compatible = "qcom,tsens-apq8064"; + reg = <0x34000 0x1000>; + qcom,qfprom = <&qfprom 0x18 0x10>, <&qfprom 0x28 0x10>; + qcom,qfprom-names = "calib", "backup_calib"; + }; diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 012fb37..389ec3e 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -19,3 +19,10 @@ config QCOM_PM QCOM Platform specific power driver to manage cores and L2 low power modes. It interface with various system drivers to put the cores in low power modes. + +config QCOM_QFPROM + tristate "QCOM QFPROM Interface" + depends on ARCH_QCOM && OF + help + Say y here to enable QFPROM support. The QFPROM provides access + functions for QFPROM data to rest of the drivers via syscon wrappers. diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index 20b329f..f5aff0a 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o obj-$(CONFIG_QCOM_PM) += spm.o +obj-$(CONFIG_QCOM_QFPROM) += qfprom.o CFLAGS_scm.o :=$(call as-instr,.arch_extension sec,-DREQUIRES_SEC=1) obj-$(CONFIG_QCOM_SCM) += scm.o scm-boot.o diff --git a/drivers/soc/qcom/qfprom.c b/drivers/soc/qcom/qfprom.c new file mode 100644 index 0000000..d00ed25 --- /dev/null +++ b/drivers/soc/qcom/qfprom.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include + +#define QFPROM_MAX_ARGS 2 + +static char *__qfprom_get_data(struct device *dev, + bool devm, int idx, int *len) +{ + struct device_node *syscon_np, *np = dev->of_node; + struct regmap *rm; + struct of_phandle_args args; + int rc, stride = 4; + u32 offset, size; + char *data; + + if (!np) + return ERR_PTR(-EINVAL); + + rc = of_parse_phandle_with_fixed_args(np, "qcom,qfprom", + QFPROM_MAX_ARGS, idx, &args); + if (rc) + return ERR_PTR(rc); + + syscon_np = args.np; + + of_property_read_u32(syscon_np, "stride", &stride); + + if (stride >= 4) + stride = 4; + + if (args.args_count < QFPROM_MAX_ARGS) { + dev_err(dev, "Insufficient qfprom arguments %d\n", + args.args_count); + return ERR_PTR(-EINVAL); + } + + rm = syscon_node_to_regmap(syscon_np); + if (IS_ERR(rm)) + return ERR_CAST(rm); + + offset = args.args[0]; + size = args.args[1]; + + of_node_put(syscon_np); + + if (devm) + data = devm_kzalloc(dev, size, GFP_KERNEL | GFP_ATOMIC); + else + data = kzalloc(size, GFP_KERNEL | GFP_ATOMIC); + + if (!data) + return ERR_PTR(-ENOMEM); + + rc = regmap_bulk_read(rm, offset, data, size/stride); + if (rc < 0) { + if (devm) + devm_kfree(dev, data); + else + kfree(data); + + return ERR_PTR(rc); + } + + *len = size; + + return data; +} + +static char *__qfprom_get_data_byname(struct device *dev, + bool devm, const char *name, int *len) +{ + int index = 0; + + if (name) + index = of_property_match_string(dev->of_node, + "qcom,qfprom-names", name); + + return __qfprom_get_data(dev, devm, index, len); +} + +char *devm_qfprom_get_data_byname(struct device *dev, + const char *name, int *len) +{ + return __qfprom_get_data_byname(dev, true, name, len); +} +EXPORT_SYMBOL_GPL(devm_qfprom_get_data_byname); + +char *devm_qfprom_get_data(struct device *dev, + int index, int *len) +{ + return __qfprom_get_data(dev, true, index, len); +} +EXPORT_SYMBOL_GPL(devm_qfprom_get_data); + +/** + * qfprom_get_data_byname(): Reads qfprom data by name + * + * @dev: device which is requesting qfprom data + * @index: name of qfprom resources specified "qcom,qfprom-names" DT property. + * @len: length of data read from qfprom. + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a data buffer. The buffer should be freed by the user once its + * finished working with it kfree. + **/ +char *qfprom_get_data_byname(struct device *dev, + const char *name, int *len) +{ + return __qfprom_get_data_byname(dev, false, name, len); +} +EXPORT_SYMBOL_GPL(qfprom_get_data_byname); + +/** + * qfprom_get_data(): Reads qfprom data from the index + * + * @dev: device which is requesting qfprom data + * @index: index into qfprom resources specified "qcom,qfprom" DT property. + * @len: length of data read from qfprom. + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a data buffer. The buffer should be freed by the user once its + * finished working with it kfree. + **/ +char *qfprom_get_data(struct device *dev, + int index, int *len) +{ + return __qfprom_get_data(dev, false, index, len); +} +EXPORT_SYMBOL_GPL(qfprom_get_data);