Received: by 10.213.65.68 with SMTP id h4csp1124218imn; Wed, 14 Mar 2018 10:16:05 -0700 (PDT) X-Google-Smtp-Source: AG47ELsWnvnZqOsvgoLdcEncznUjIgSwqXdk4RtRma27qo0lSVqSLngqYrAP0VRp5c87DLuMF9CX X-Received: by 10.101.65.5 with SMTP id w5mr4349302pgp.214.1521047765463; Wed, 14 Mar 2018 10:16:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1521047765; cv=none; d=google.com; s=arc-20160816; b=0QRBvEHrCvQgyrV6S86j+MwWgY8zzSZX/exMXB4r5JNfsS3RFO6EulZ0cIABD2vzVN 6q/W5eto8FGLR8yfelv1Srx2aOE5e2fqdOHQcB+zjsK8sQcJVsXv/dFWH+Ind7XkbcR5 thEsZrn2O9ZmT6SlV8Iy10Qs6xnSKxb4FUl0Vnfo3mdjHPBKbT6ssAPf8Fb8ANz2bGLZ +6h8QL3WEwrZBovLnQ2jWgDDfol3m8MxSNfz7XOWERRYWkrwuOlRXC9jf4HzzTWaFmhg fpi49b0L8mZhoMhoeYn3+t24b89MlJbeiiCFXGFskqUXlsUoTMczzDYlO2rFswA0jLmG Ocyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:dmarc-filter:dkim-signature:dkim-signature :arc-authentication-results; bh=0cLqPQVwfxkLl6j5i2kO1aAycGfbX1F7k2A7MUevKt4=; b=fG02fbeN01yje49RHFkED3doHTAsF11TTjAvWWKJfGY7JAnqDVskTo3hKT2WOVckBs dqFTJ9y3QjtV9wb5dGbL5Yra5CsrzlLZL5taei/NDzg/dVTkAVtQAVpST11DgDhOiBCF 8F12CUBDlPfIIgX5mhwcbLA4qfRpbdDJJuc9Z9mgYtihefkPlhB0sSrWDmhKiXj835Ju Sc5kN+jku0ri4H5EEy4k8rIhu2uma4XbXBKQ7WfgopToFMVau60Ppzuc82yY1JiWnCAA CXFVGssndzUEqbT39YNhh3f3sBs782fJMMDxctWzKxAYC8HM/RTSah+n0WpQmdWTbb1l B7Qg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=Ipa1U/Lt; dkim=pass header.i=@codeaurora.org header.s=default header.b=UAuFQg04; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a89-v6si2204418pla.527.2018.03.14.10.15.50; Wed, 14 Mar 2018 10:16:05 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@codeaurora.org header.s=default header.b=Ipa1U/Lt; dkim=pass header.i=@codeaurora.org header.s=default header.b=UAuFQg04; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752131AbeCNRNm (ORCPT + 99 others); Wed, 14 Mar 2018 13:13:42 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:52524 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751700AbeCNRNj (ORCPT ); Wed, 14 Mar 2018 13:13:39 -0400 Received: by smtp.codeaurora.org (Postfix, from userid 1000) id 7858760AF9; Wed, 14 Mar 2018 17:13:38 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1521047618; bh=27v0Hn9hdCuChVR4e2SQl6U0I8sIldfXWgJOmy4tF+o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Ipa1U/LtD2p8fTxbPdfDSZrvyM9QmzcAc3X6XhoEKpTv4nwAofuAsSDck9f9o4mqN 7q+u7DkoTyagvMIEx8jSLfLQDH2n9IPpUUfWUp3GTeuzv/rINknQoVGEZXT1owywt+ LXakOmOTz2VIZyuF41PoWfMkazM1EejrcRDBC3ZU= X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on pdx-caf-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.8 required=2.0 tests=ALL_TRUSTED,BAYES_00, DKIM_SIGNED,T_DKIM_INVALID autolearn=no autolearn_force=no version=3.4.0 Received: from codeaurora.org (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: ilina@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id C1DA360591; Wed, 14 Mar 2018 17:13:35 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=codeaurora.org; s=default; t=1521047616; bh=27v0Hn9hdCuChVR4e2SQl6U0I8sIldfXWgJOmy4tF+o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=UAuFQg04SOZVD4W9mqhhKF/rkh4HPr2fSYEIq2n/qpO66iBiFmfxwSupSqaoIuzHO jqlmAqlUOoWc3OITvT0vdwg9LLzkgK6nYJsuHYkY/wuaTzZ/S7Un1X/kD/sgJD2ddP W8B+NhSeuAKD1GsVKH70suAfWUfNrCM+dh1jqN38= DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org C1DA360591 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none (p=none dis=none) header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=none smtp.mailfrom=ilina@codeaurora.org From: Lina Iyer To: andy.gross@linaro.org, david.brown@linaro.org, linux-arm-msm@vger.kernel.org Cc: linux-soc@vger.kernel.org, rnayak@codeaurora.org, bjorn.andersson@linaro.org, linux-kernel@vger.kernel.org, sboyd@kernel.org, Lina Iyer , Mahesh Sivasubramanian Subject: [PATCH v5 1/2] drivers: qcom: add command DB driver Date: Wed, 14 Mar 2018 11:13:29 -0600 Message-Id: <20180314171330.1828-2-ilina@codeaurora.org> X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180314171330.1828-1-ilina@codeaurora.org> References: <20180314171330.1828-1-ilina@codeaurora.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mahesh Sivasubramanian Command DB is a simple database in the shared memory of QCOM SoCs, that provides information regarding shared resources. Some shared resources in the SoC have properties that are probed dynamically at boot by the remote processor. The information pertaining to the SoC and the platform are made available in the shared memory. Drivers can query this information using predefined strings. Signed-off-by: Mahesh Sivasubramanian Signed-off-by: Lina Iyer --- Changes in v5: - Use strncmp - Add check in probe to ensure the location at dictionary address is same as the one specified in reserved-memory - Whitespace fixes - Comments updated --- drivers/of/platform.c | 1 + drivers/soc/qcom/Kconfig | 9 ++ drivers/soc/qcom/Makefile | 1 + drivers/soc/qcom/cmd-db.c | 326 ++++++++++++++++++++++++++++++++++++++++++++++ include/soc/qcom/cmd-db.h | 45 +++++++ 5 files changed, 382 insertions(+) create mode 100644 drivers/soc/qcom/cmd-db.c create mode 100644 include/soc/qcom/cmd-db.h diff --git a/drivers/of/platform.c b/drivers/of/platform.c index c00d81dfac0b..26fb43847f4b 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -494,6 +494,7 @@ EXPORT_SYMBOL_GPL(of_platform_default_populate); #ifndef CONFIG_PPC static const struct of_device_id reserved_mem_matches[] = { { .compatible = "qcom,rmtfs-mem" }, + { .compatible = "qcom,cmd-db" }, { .compatible = "ramoops" }, {} }; diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index e050eb83341d..b12868a2b92d 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -3,6 +3,15 @@ # menu "Qualcomm SoC drivers" +config QCOM_COMMAND_DB + bool "Qualcomm Command DB" + depends on (ARCH_QCOM && OF) || COMPILE_TEST + help + Command DB queries shared memory by key string for shared system + resources. Platform drivers that require to set state of a shared + resource on a RPM-hardened platform must use this database to get + SoC specific identifier and information for the shared resources. + config QCOM_GLINK_SSR tristate "Qualcomm Glink SSR driver" depends on RPMSG diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile index dcebf2814e6d..bbd1230fc441 100644 --- a/drivers/soc/qcom/Makefile +++ b/drivers/soc/qcom/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c new file mode 100644 index 000000000000..83e7e530ea38 --- /dev/null +++ b/drivers/soc/qcom/cmd-db.c @@ -0,0 +1,326 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define NUM_PRIORITY 2 +#define MAX_SLV_ID 8 +#define CMD_DB_MAGIC 0x0C0330DBUL +#define SLAVE_ID_MASK 0x7 +#define SLAVE_ID_SHIFT 16 + +#define ENTRY_HEADER(hdr) ((void *)cmd_db_header + \ + sizeof(*cmd_db_header) + \ + hdr->header_offset) + +#define RSC_OFFSET(hdr, ent) ((void *)cmd_db_header + \ + sizeof(*cmd_db_header) + \ + hdr.data_offset + ent.offset) + +/** + * struct entry_header: header for each entry in cmddb + * + * @id: resource's identifier + * @priority: unused + * @addr: the address of the resource + * @len: length of the data + * @offset: offset from :@data_offset, start of the data + */ +struct entry_header { + u64 id; + u32 priority[NUM_PRIORITY]; + u32 addr; + u16 len; + u16 offset; +}; + +/** + * struct rsc_hdr: resource header information + * + * @slv_id: id for the resource + * @header_offset: entry's header at offset from the end of the cmd_db_header + * @data_offset: entry's data at offset from the end of the cmd_db_header + * @cnt: number of entries for HW type + * @version: MSB is major, LSB is minor + * @reserved: reserved for future use. + */ +struct rsc_hdr { + u16 slv_id; + u16 header_offset; + u16 data_offset; + u16 cnt; + u16 version; + u16 reserved[3]; +}; + +/** + * struct cmd_db_header: The DB header information + * + * @version: The cmd db version + * @magic_number: constant expected in the database + * @header: array of resources + * @checksum: checksum for the header. Unused. + * @reserved: reserved memory + * @data: driver specific data + */ +struct cmd_db_header { + u32 version; + u32 magic_num; + struct rsc_hdr header[MAX_SLV_ID]; + u32 checksum; + u32 reserved; + u8 data[]; +}; + +/** + * DOC: Description of the Command DB database. + * + * At the start of the command DB memory is the cmd_db_header structure. + * The cmd_db_header holds the version, checksum, magic key as well as an + * array for header for each slave (depicted by the rsc_header). Each h/w + * based accelerator is a 'slave' (shared resource) and has slave id indicating + * the type of accelerator. The rsc_header is the header for such individual + * slaves of a given type. The entries for each of these slaves begin at the + * rsc_hdr.header_offset. In addition each slave could have auxiliary data + * that may be needed by the driver. The data for the slave starts at the + * entry_header.offset to the location pointed to by the rsc_hdr.data_offset. + * + * Drivers have a stringified key to a slave/resource. They can query the slave + * information and get the slave id and the auxiliary data and the length of the + * data. Using this information, they can format the request to be sent to the + * h/w accelerator and request a resource state. + */ + +static struct cmd_db_header *cmd_db_header; + +/** + * cmd_db_ready - Indicates if command DB is available + * + * Return: 0 on success, errno otherwise + */ +int cmd_db_ready(void) +{ + if (cmd_db_header == NULL) + return -EPROBE_DEFER; + else if (cmd_db_header->magic_num != CMD_DB_MAGIC) + return -EINVAL; + + return 0; +} +EXPORT_SYMBOL(cmd_db_ready); + +static u64 cmd_db_get_u64_id(const char *id) +{ + u64 rsc_id = 0; + u8 *ch = (u8 *)&rsc_id; + + strncpy(ch, id, min(strlen(id), sizeof(rsc_id))); + + return rsc_id; +} + +static int cmd_db_get_header(u64 query, struct entry_header *eh, + struct rsc_hdr *rh) +{ + struct rsc_hdr *rsc_hdr; + struct entry_header *ent; + int ret, i, j; + + ret = cmd_db_ready(); + if (ret) + return ret; + + if (!eh || !rh) + return -EINVAL; + + for (i = 0; i < MAX_SLV_ID; i++) { + rsc_hdr = &cmd_db_header->header[i]; + if (!rsc_hdr->slv_id) + break; + + ent = ENTRY_HEADER(rsc_hdr); + for (j = 0; j < rsc_hdr->cnt; j++, ent++) { + if (ent->id == query) + break; + } + + if (j < rsc_hdr->cnt) { + memcpy(eh, ent, sizeof(*ent)); + memcpy(rh, rsc_hdr, sizeof(*rh)); + return 0; + } + } + + return -ENODEV; +} + +static int cmd_db_get_header_by_rsc_id(const char *id, + struct entry_header *ent_hdr, + struct rsc_hdr *rsc_hdr) +{ + u64 rsc_id = cmd_db_get_u64_id(id); + + return cmd_db_get_header(rsc_id, ent_hdr, rsc_hdr); +} + +/** + * cmd_db_read_addr() - Query command db for resource id address. + * + * @id: resource id to query for address + * + * Return: resource address on success, 0 on error + * + * This is used to retrieve resource address based on resource + * id. + */ +u32 cmd_db_read_addr(const char *id) +{ + int ret; + struct entry_header ent; + struct rsc_hdr rsc_hdr; + + ret = cmd_db_get_header_by_rsc_id(id, &ent, &rsc_hdr); + + return ret < 0 ? 0 : ent.addr; +} +EXPORT_SYMBOL(cmd_db_read_addr); + +/** + * cmd_db_read_aux_data() - Query command db for aux data. + * + * @id: Resource to retrieve AUX Data on. + * @data: Data buffer to copy returned aux data to. Returns size on NULL + * @len: Caller provides size of data buffer passed in. + * + * Return: size of data on success, errno otherwise + */ +int cmd_db_read_aux_data(const char *id, u8 *data, size_t len) +{ + int ret; + struct entry_header ent; + struct rsc_hdr rsc_hdr; + + if (!data) + return -EINVAL; + + ret = cmd_db_get_header_by_rsc_id(id, &ent, &rsc_hdr); + if (ret) + return ret; + + if (len < ent.len) + return -EINVAL; + + len = min_t(u16, ent.len, len); + memcpy(data, RSC_OFFSET(rsc_hdr, ent), len); + + return len; +} +EXPORT_SYMBOL(cmd_db_read_aux_data); + +/** + * cmd_db_read_aux_data_len - Get the length of the auxillary data stored in DB. + * + * @id: Resource to retrieve AUX Data. + * + * Return: size on success, 0 on error + */ +size_t cmd_db_read_aux_data_len(const char *id) +{ + int ret; + struct entry_header ent; + struct rsc_hdr rsc_hdr; + + ret = cmd_db_get_header_by_rsc_id(id, &ent, &rsc_hdr); + + return ret < 0 ? 0 : ent.len; +} +EXPORT_SYMBOL(cmd_db_read_aux_data_len); + +/** + * cmd_db_read_slave_id - Get the slave ID for a given resource address + * + * @id: Resource id to query the DB for version + * + * Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error + */ +enum cmd_db_hw_type cmd_db_read_slave_id(const char *id) +{ + int ret; + struct entry_header ent; + struct rsc_hdr rsc_hdr; + + ret = cmd_db_get_header_by_rsc_id(id, &ent, &rsc_hdr); + + return ret < 0 ? CMD_DB_HW_INVALID : + (ent.addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK; +} +EXPORT_SYMBOL(cmd_db_read_slave_id); + +static int cmd_db_dev_probe(struct platform_device *pdev) +{ + struct reserved_mem *rmem; + u32 *dict; + int ret = 0; + const __be32 *db_start; + + rmem = of_reserved_mem_lookup(pdev->dev.of_node); + if (!rmem) { + dev_err(&pdev->dev, "failed to acquire memory region\n"); + return -EINVAL; + } + + dict = memremap(rmem->base, rmem->size, MEMREMAP_WB); + if (IS_ERR(dict)) + return -ENOMEM; + + db_start = of_get_address(pdev->dev.of_node, 1, NULL, NULL); + if (!db_start) + return -EINVAL; + + if (be32_to_cpup(db_start + 1) != *dict) + dev_warn(&pdev->dev, + "Incorrect Command DB location specified in DT\n"); + + cmd_db_header = memremap(*dict, *(dict + 0x4), MEMREMAP_WB); + if (IS_ERR_OR_NULL(cmd_db_header)) { + ret = PTR_ERR(cmd_db_header); + cmd_db_header = NULL; + goto done; + } + + if (cmd_db_header->magic_num != CMD_DB_MAGIC) { + ret = -EINVAL; + dev_err(&pdev->dev, "Invalid Command DB Magic\n"); + goto done; + } +done: + memunmap(dict); + return ret; +} + +static const struct of_device_id cmd_db_match_table[] = { + { .compatible = "qcom,cmd-db" }, + { }, +}; + +static struct platform_driver cmd_db_dev_driver = { + .probe = cmd_db_dev_probe, + .driver = { + .name = "cmd-db", + .of_match_table = cmd_db_match_table, + }, +}; + +static int __init cmd_db_device_init(void) +{ + return platform_driver_register(&cmd_db_dev_driver); +} +arch_initcall(cmd_db_device_init); diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h new file mode 100644 index 000000000000..578180cbc134 --- /dev/null +++ b/include/soc/qcom/cmd-db.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. */ + +#ifndef __QCOM_COMMAND_DB_H__ +#define __QCOM_COMMAND_DB_H__ + + +enum cmd_db_hw_type { + CMD_DB_HW_INVALID = 0, + CMD_DB_HW_MIN = 3, + CMD_DB_HW_ARC = CMD_DB_HW_MIN, + CMD_DB_HW_VRM = 4, + CMD_DB_HW_BCM = 5, + CMD_DB_HW_MAX = CMD_DB_HW_BCM, + CMD_DB_HW_ALL = 0xff, +}; + +#if IS_ENABLED(CONFIG_QCOM_COMMAND_DB) +u32 cmd_db_read_addr(const char *resource_id); + +int cmd_db_read_aux_data(const char *resource_id, u8 *data, size_t len); + +size_t cmd_db_read_aux_data_len(const char *resource_id); + +enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id); + +int cmd_db_ready(void); +#else +static inline u32 cmd_db_read_addr(const char *resource_id) +{ return 0; } + +static inline int cmd_db_read_aux_data(const char *resource_id, u8 *data, + size_t len) +{ return -ENODEV; } + +static inline size_t cmd_db_read_aux_data_len(const char *resource_id) +{ return -ENODEV; } + +static inline enum cmd_db_hw_type cmd_db_read_slave_id(const char *resource_id) +{ return -ENODEV; } + +static inline int cmd_db_ready(void) +{ return -ENODEV; } +#endif /* CONFIG_QCOM_COMMAND_DB */ +#endif /* __QCOM_COMMAND_DB_H__ */ -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project