Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756724AbcJTOHD (ORCPT ); Thu, 20 Oct 2016 10:07:03 -0400 Received: from smtp.codeaurora.org ([198.145.29.96]:41591 "EHLO smtp.codeaurora.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754438AbcJTOHA (ORCPT ); Thu, 20 Oct 2016 10:07:00 -0400 DMARC-Filter: OpenDMARC Filter v1.3.1 smtp.codeaurora.org 0365161295 Authentication-Results: pdx-caf-mail.web.codeaurora.org; dmarc=none header.from=codeaurora.org Authentication-Results: pdx-caf-mail.web.codeaurora.org; spf=pass smtp.mailfrom=kimran@codeaurora.org From: Imran Khan To: andy.gross@linaro.org Cc: Imran Khan , David Brown , Rob Herring , Mark Rutland , linux-arm-msm@vger.kernel.org (open list:ARM/QUALCOMM SUPPORT), linux-soc@vger.kernel.org (open list:ARM/QUALCOMM SUPPORT), devicetree@vger.kernel.org (open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS), linux-kernel@vger.kernel.org (open list) Subject: [PATCH] soc: qcom: Add SoC info driver Date: Thu, 20 Oct 2016 19:36:22 +0530 Message-Id: <1476972386-28655-1-git-send-email-kimran@codeaurora.org> X-Mailer: git-send-email 1.9.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 40886 Lines: 1424 The SoC info driver provides information such as Chip ID, Chip family, serial number and other such details about Qualcomm SoCs. Signed-off-by: Imran Khan --- .../devicetree/bindings/soc/qcom/qcom,socinfo.txt | 18 + drivers/soc/qcom/socinfo.c | 1173 ++++++++++++++++++++ include/linux/soc/qcom/socinfo.h | 198 ++++ 3 files changed, 1389 insertions(+) create mode 100644 Documentation/devicetree/bindings/soc/qcom/qcom,socinfo.txt create mode 100644 drivers/soc/qcom/socinfo.c create mode 100644 include/linux/soc/qcom/socinfo.h diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,socinfo.txt b/Documentation/devicetree/bindings/soc/qcom/qcom,socinfo.txt new file mode 100644 index 0000000..1f26299 --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/qcom,socinfo.txt @@ -0,0 +1,18 @@ +Qualcomm SoC Information (socinfo) Driver binding + +This binding describes the Qualcomm SoC Information Driver, which provides +information such as chip id, chip family, serial number and other such +details about Qualcomm SoCs. + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,socinfo" + += EXAMPLE + +The following example represents a socinfo node. + + socinfo { + compatible = "qcom,socinfo"; + }; diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c new file mode 100644 index 0000000..dc26028 --- /dev/null +++ b/drivers/soc/qcom/socinfo.c @@ -0,0 +1,1173 @@ +/* + * Copyright (c) 2009-2016, 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 + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +/* + * SOC Info Routines + * + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +#define BUILD_ID_LENGTH 32 +#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32 +#define SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE 128 +#define SMEM_IMAGE_VERSION_SIZE 4096 +#define SMEM_IMAGE_VERSION_NAME_SIZE 75 +#define SMEM_IMAGE_VERSION_VARIANT_SIZE 20 +#define SMEM_IMAGE_VERSION_VARIANT_OFFSET 75 +#define SMEM_IMAGE_VERSION_OEM_SIZE 32 +#define SMEM_IMAGE_VERSION_OEM_OFFSET 96 +#define SMEM_IMAGE_VERSION_PARTITION_APPS 10 +#define SMEM_ITEM_SIZE_ALIGN 8 +/* + * Shared memory identifiers, used to acquire handles to respective memory + * region. + */ +#define SMEM_IMAGE_VERSION_TABLE 469 +#define SMEM_HW_SW_BUILD_ID 137 + +const char *hw_platform[] = { + [HW_PLATFORM_UNKNOWN] = "Unknown", + [HW_PLATFORM_SURF] = "Surf", + [HW_PLATFORM_FFA] = "FFA", + [HW_PLATFORM_FLUID] = "Fluid", + [HW_PLATFORM_SVLTE_FFA] = "SVLTE_FFA", + [HW_PLATFORM_SVLTE_SURF] = "SLVTE_SURF", + [HW_PLATFORM_MTP_MDM] = "MDM_MTP_NO_DISPLAY", + [HW_PLATFORM_MTP] = "MTP", + [HW_PLATFORM_RCM] = "RCM", + [HW_PLATFORM_LIQUID] = "Liquid", + [HW_PLATFORM_DRAGON] = "Dragon", + [HW_PLATFORM_QRD] = "QRD", + [HW_PLATFORM_HRD] = "HRD", + [HW_PLATFORM_DTV] = "DTV", + [HW_PLATFORM_STP] = "STP", + [HW_PLATFORM_SBC] = "SBC", +}; + +const char *qrd_hw_platform_subtype[] = { + [PLATFORM_SUBTYPE_QRD] = "QRD", + [PLATFORM_SUBTYPE_SKUAA] = "SKUAA", + [PLATFORM_SUBTYPE_SKUF] = "SKUF", + [PLATFORM_SUBTYPE_SKUAB] = "SKUAB", + [PLATFORM_SUBTYPE_SKUG] = "SKUG", + [PLATFORM_SUBTYPE_QRD_INVALID] = "INVALID", +}; + +const char *hw_platform_subtype[] = { + [PLATFORM_SUBTYPE_UNKNOWN] = "Unknown", + [PLATFORM_SUBTYPE_CHARM] = "charm", + [PLATFORM_SUBTYPE_STRANGE] = "strange", + [PLATFORM_SUBTYPE_STRANGE_2A] = "strange_2a", + [PLATFORM_SUBTYPE_INVALID] = "Invalid", +}; + +/* Used to parse shared memory. Must match the modem. */ +struct socinfo_v0_1 { + uint32_t format; + uint32_t id; + uint32_t version; + char build_id[BUILD_ID_LENGTH]; +}; + +struct socinfo_v0_2 { + struct socinfo_v0_1 v0_1; + uint32_t raw_id; + uint32_t raw_version; +}; + +struct socinfo_v0_3 { + struct socinfo_v0_2 v0_2; + uint32_t hw_platform; +}; + +struct socinfo_v0_4 { + struct socinfo_v0_3 v0_3; + uint32_t platform_version; +}; + +struct socinfo_v0_5 { + struct socinfo_v0_4 v0_4; + uint32_t accessory_chip; +}; + +struct socinfo_v0_6 { + struct socinfo_v0_5 v0_5; + uint32_t hw_platform_subtype; +}; + +struct socinfo_v0_7 { + struct socinfo_v0_6 v0_6; + uint32_t pmic_model; + uint32_t pmic_die_revision; +}; + +struct socinfo_v0_8 { + struct socinfo_v0_7 v0_7; + uint32_t pmic_model_1; + uint32_t pmic_die_revision_1; + uint32_t pmic_model_2; + uint32_t pmic_die_revision_2; +}; + +struct socinfo_v0_9 { + struct socinfo_v0_8 v0_8; + uint32_t foundry_id; +}; + +struct socinfo_v0_10 { + struct socinfo_v0_9 v0_9; + uint32_t serial_number; +}; + +struct socinfo_v0_11 { + struct socinfo_v0_10 v0_10; + uint32_t num_pmics; + uint32_t pmic_array_offset; +}; + +struct socinfo_v0_12 { + struct socinfo_v0_11 v0_11; + uint32_t chip_family; + uint32_t raw_device_family; + uint32_t raw_device_number; +}; + +static union { + struct socinfo_v0_1 v0_1; + struct socinfo_v0_2 v0_2; + struct socinfo_v0_3 v0_3; + struct socinfo_v0_4 v0_4; + struct socinfo_v0_5 v0_5; + struct socinfo_v0_6 v0_6; + struct socinfo_v0_7 v0_7; + struct socinfo_v0_8 v0_8; + struct socinfo_v0_9 v0_9; + struct socinfo_v0_10 v0_10; + struct socinfo_v0_11 v0_11; + struct socinfo_v0_12 v0_12; +} *socinfo; + +/* max socinfo format version supported */ +#define MAX_SOCINFO_FORMAT SOCINFO_VERSION(0, 12) + +static struct qcom_soc_info cpu_of_id[] = { + + [MSM_UNKNOWN_ID] = {MSM_CPU_UNKNOWN, "Unknown CPU"}, + + /* 8x60 IDs */ + [MSM_8960_ID] = {MSM_CPU_8960, "MSM8960"}, + + /* 8x64 IDs */ + [APQ_8064_ID] = {MSM_CPU_8064, "APQ8064"}, + [MPQ_8064_ID] = {MSM_CPU_8064, "MPQ8064"}, + + /* 8x60A IDs */ + [MSM_8660A_ID] = {MSM_CPU_8960, "MSM8660A"}, + [MSM_8260A_ID] = {MSM_CPU_8960, "MSM8260A"}, + [APQ_8060A_ID] = {MSM_CPU_8960, "APQ8060A"}, + + /* 8x74 IDs */ + [MSM_8974_ID] = {MSM_CPU_8974, "MSM8974"}, + [APQ_8074_ID] = {MSM_CPU_8974, "APQ8074"}, + [MSM_8274_ID] = {MSM_CPU_8974, "MSM8274"}, + [MSM_8674_ID] = {MSM_CPU_8974, "MSM8674"}, + + /* 8x74AA IDs */ + [APQ_8074_AA_ID] = {MSM_CPU_8974PRO_AA, "APQ8074-AA"}, + [MSM_8274_AA_ID] = {MSM_CPU_8974PRO_AA, "MSM8274-AA"}, + [MSM_8674_AA_ID] = {MSM_CPU_8974PRO_AA, "MSM8674-AA"}, + [MSM_8974_AA_ID] = {MSM_CPU_8974PRO_AA, "MSM8974-AA"}, + + /* 8x74AB IDs */ + [APQ_8074_AB_ID] = {MSM_CPU_8974PRO_AB, "APQ8074-AB"}, + [MSM_8274_AB_ID] = {MSM_CPU_8974PRO_AB, "MSM8274-AB"}, + [MSM_8674_AB_ID] = {MSM_CPU_8974PRO_AB, "MSM8674-AB"}, + [MSM_8974_AB_ID] = {MSM_CPU_8974PRO_AB, "MSM8974-AB"}, + + /* 8x74AC IDs */ + [MSM_8974PRO_ID] = {MSM_CPU_8974PRO_AC, "MSM8974PRO"}, + [APQ_8074PRO_ID] = {MSM_CPU_8974PRO_AC, "APQ8074PRO"}, + [MSM_8274PRO_ID] = {MSM_CPU_8974PRO_AC, "MSM8274PRO"}, + [MSM_8674PRO_ID] = {MSM_CPU_8974PRO_AC, "MSM8674PRO"}, + + /* 8x60AB IDs */ + [MSM_8960AB_ID] = {MSM_CPU_8960AB, "MSM8960AB"}, + [APQ_8060AB_ID] = {MSM_CPU_8960AB, "APQ8060AB"}, + [MSM_8260AB_ID] = {MSM_CPU_8960AB, "MSM8260AB"}, + [MSM_8660AB_ID] = {MSM_CPU_8960AB, "MSM8660AB"}, + + /* 8x84 IDs */ + [APQ_8084_ID] = {MSM_CPU_8084, "APQ8084"}, + + /* 8x16 IDs */ + [MSM_8916_ID] = {MSM_CPU_8916, "MSM8916"}, + [APQ_8016_ID] = {MSM_CPU_8916, "APQ8016"}, + [MSM_8216_ID] = {MSM_CPU_8916, "MSM8216"}, + [MSM_8116_ID] = {MSM_CPU_8916, "MSM8116"}, + [MSM_8616_ID] = {MSM_CPU_8916, "MSM8616"}, + + /* 8x96 IDs */ + [MSM_8996_ID] = {MSM_CPU_8996, "MSM8996"}, + [MSM_8996AU_ID] = {MSM_CPU_8996, "MSM8996AU"}, + [APQ_8096AU_ID] = {MSM_CPU_8996, "APQ8096AU"}, + [APQ8096_ID] = {MSM_CPU_8996, "APQ8096"}, + [MSM_8996SG_ID] = {MSM_CPU_8996, "MSM8996SG"}, + [APQ_8096SG_ID] = {MSM_CPU_8996, "APQ8096SG"}, + + /* + * Uninitialized IDs are not known to run Linux. + * MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are + * considered as unknown CPU. + */ +}; + +static enum qcom_cpu cur_cpu; +static int current_image; +static uint32_t socinfo_format; + +static struct socinfo_v0_1 dummy_socinfo = { + .format = SOCINFO_VERSION(0, 1), + .version = 1, +}; + +static char *socinfo_get_id_string(void) +{ + return (socinfo) ? cpu_of_id[socinfo->v0_1.id].soc_id_string : NULL; +} + +static uint32_t socinfo_get_accessory_chip(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 5) ? + socinfo->v0_5.accessory_chip : 0) + : 0; +} + +static uint32_t socinfo_get_foundry_id(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 9) ? + socinfo->v0_9.foundry_id : 0) + : 0; +} + +static uint32_t socinfo_get_chip_family(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 12) ? + socinfo->v0_12.chip_family : 0) + : 0; +} + +static uint32_t socinfo_get_raw_device_family(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 12) ? + socinfo->v0_12.raw_device_family : 0) + : 0; +} + +static uint32_t socinfo_get_raw_device_number(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 12) ? + socinfo->v0_12.raw_device_number : 0) + : 0; +} + +static char *socinfo_get_image_version_base_address(struct device *dev) +{ + size_t size, size_in; + void *ptr; + + ptr = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_IMAGE_VERSION_TABLE, + &size); + if (!ptr) + return 0; + + size_in = ALIGN(SMEM_IMAGE_VERSION_SIZE, SMEM_ITEM_SIZE_ALIGN); + if (size_in != size) { + dev_err(dev, "Wrong size for smem item\n"); + return 0; + } + + return ptr; +} + +uint32_t socinfo_get_id(void) +{ + return (socinfo) ? socinfo->v0_1.id : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_id); + +uint32_t socinfo_get_version(void) +{ + return (socinfo) ? socinfo->v0_1.version : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_version); + +char *socinfo_get_build_id(void) +{ + return (socinfo) ? socinfo->v0_1.build_id : NULL; +} +EXPORT_SYMBOL_GPL(socinfo_get_build_id); + +uint32_t socinfo_get_raw_id(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 2) ? + socinfo->v0_2.raw_id : 0) + : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_raw_id); + +uint32_t socinfo_get_raw_version(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 2) ? + socinfo->v0_2.raw_version : 0) + : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_raw_version); + +uint32_t socinfo_get_platform_type(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 3) ? + socinfo->v0_3.hw_platform : 0) + : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_platform_type); + +uint32_t socinfo_get_platform_version(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 4) ? + socinfo->v0_4.platform_version : 0) + : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_platform_version); + +uint32_t socinfo_get_platform_subtype(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 6) ? + socinfo->v0_6.hw_platform_subtype : 0) + : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_platform_subtype); + +uint32_t socinfo_get_serial_number(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 10) ? + socinfo->v0_10.serial_number : 0) + : 0; +} +EXPORT_SYMBOL_GPL(socinfo_get_serial_number); + +enum qcom_pmic_model socinfo_get_pmic_model(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 7) ? + socinfo->v0_7.pmic_model : PMIC_MODEL_UNKNOWN) + : PMIC_MODEL_UNKNOWN; +} + +uint32_t socinfo_get_pmic_die_revision(void) +{ + return socinfo ? + (socinfo_format >= SOCINFO_VERSION(0, 7) ? + socinfo->v0_7.pmic_die_revision : 0) + : 0; +} + +enum qcom_cpu socinfo_get_qcom_cpu(void) +{ + return cur_cpu; +} +EXPORT_SYMBOL_GPL(socinfo_get_qcom_cpu); + +/* socinfo: sysfs functions */ + +static ssize_t +qcom_get_vendor(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "Qualcomm\n"); +} + +static ssize_t +qcom_get_raw_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_raw_id()); +} + +static ssize_t +qcom_get_raw_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_raw_version()); +} + +static ssize_t +qcom_get_build_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%-.32s\n", + socinfo_get_build_id()); +} + +static ssize_t +qcom_get_hw_platform(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + uint32_t hw_type; + + hw_type = socinfo_get_platform_type(); + + return snprintf(buf, PAGE_SIZE, "%-.32s\n", + hw_platform[hw_type]); +} + +static ssize_t +qcom_get_platform_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_platform_version()); +} + +static ssize_t +qcom_get_accessory_chip(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_accessory_chip()); +} + +static ssize_t +qcom_get_platform_subtype(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + uint32_t hw_subtype; + + hw_subtype = socinfo_get_platform_subtype(); + if (socinfo_get_platform_type() == HW_PLATFORM_QRD) { + if (hw_subtype >= PLATFORM_SUBTYPE_QRD_INVALID) { + pr_err("Invalid hardware platform sub type for qrd found\n"); + hw_subtype = PLATFORM_SUBTYPE_QRD_INVALID; + } + return snprintf(buf, PAGE_SIZE, "%-.32s\n", + qrd_hw_platform_subtype[hw_subtype]); + } else { + if (hw_subtype >= PLATFORM_SUBTYPE_INVALID) { + pr_err("Invalid hardware platform subtype\n"); + hw_subtype = PLATFORM_SUBTYPE_INVALID; + } + return snprintf(buf, PAGE_SIZE, "%-.32s\n", + hw_platform_subtype[hw_subtype]); + } +} + +static ssize_t +qcom_get_platform_subtype_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + uint32_t hw_subtype; + + hw_subtype = socinfo_get_platform_subtype(); + return snprintf(buf, PAGE_SIZE, "%u\n", + hw_subtype); +} + +static ssize_t +qcom_get_foundry_id(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_foundry_id()); +} + +static ssize_t +qcom_get_serial_number(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_serial_number()); +} + +static ssize_t +qcom_get_chip_family(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_chip_family()); +} + +static ssize_t +qcom_get_raw_device_family(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_raw_device_family()); +} + +static ssize_t +qcom_get_raw_device_number(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0x%x\n", + socinfo_get_raw_device_number()); +} + +static ssize_t +qcom_get_pmic_model(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_pmic_model()); +} + +static ssize_t +qcom_get_pmic_die_revision(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", + socinfo_get_pmic_die_revision()); +} + +static ssize_t +qcom_get_image_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *string_address; + + string_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(string_address)) { + pr_err("Failed to get image version base address"); + return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "Unknown"); + } + string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + return snprintf(buf, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s\n", + string_address); +} + +static ssize_t +qcom_set_image_version(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + char *store_address; + + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + return count; + store_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(store_address)) { + pr_err("Failed to get image version base address"); + return count; + } + store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + snprintf(store_address, SMEM_IMAGE_VERSION_NAME_SIZE, "%-.75s", buf); + return count; +} + +static ssize_t +qcom_get_image_variant(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *string_address; + + string_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(string_address)) { + pr_err("Failed to get image version base address"); + return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, + "Unknown"); + } + string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + string_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; + return snprintf(buf, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s\n", + string_address); +} + +static ssize_t +qcom_set_image_variant(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + char *store_address; + + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + return count; + store_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(store_address)) { + pr_err("Failed to get image version base address"); + return count; + } + store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + store_address += SMEM_IMAGE_VERSION_VARIANT_OFFSET; + snprintf(store_address, SMEM_IMAGE_VERSION_VARIANT_SIZE, "%-.20s", buf); + return count; +} + +static ssize_t +qcom_get_image_crm_version(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + char *string_address; + + string_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(string_address)) { + pr_err("Failed to get image version base address"); + return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "Unknown"); + } + string_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + string_address += SMEM_IMAGE_VERSION_OEM_OFFSET; + return snprintf(buf, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s\n", + string_address); +} + +static ssize_t +qcom_set_image_crm_version(struct device *dev, + struct device_attribute *attr, + const char *buf, + size_t count) +{ + char *store_address; + + if (current_image != SMEM_IMAGE_VERSION_PARTITION_APPS) + return count; + store_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(store_address)) { + pr_err("Failed to get image version base address"); + return count; + } + store_address += current_image * SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + store_address += SMEM_IMAGE_VERSION_OEM_OFFSET; + snprintf(store_address, SMEM_IMAGE_VERSION_OEM_SIZE, "%-.32s", buf); + return count; +} + +static ssize_t +qcom_get_image_number(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", + current_image); +} + +static ssize_t +qcom_select_image(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int ret, digit; + + ret = kstrtoint(buf, 10, &digit); + if (ret) + return ret; + if (digit >= 0 && digit < SMEM_IMAGE_VERSION_BLOCKS_COUNT) + current_image = digit; + else + current_image = 0; + return count; +} + +static ssize_t +qcom_get_images(struct device *dev, + struct device_attribute *attr, char *buf) +{ + int pos = 0; + int image; + char *image_address; + + image_address = socinfo_get_image_version_base_address(dev); + if (IS_ERR_OR_NULL(image_address)) + return snprintf(buf, PAGE_SIZE, "Unavailable\n"); + + *buf = '\0'; + for (image = 0; image < SMEM_IMAGE_VERSION_BLOCKS_COUNT; image++) { + if (*image_address == '\0') { + image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + continue; + } + + pos += snprintf(buf + pos, PAGE_SIZE - pos, "%d:\n", + image); + pos += snprintf(buf + pos, PAGE_SIZE - pos, + "\tCRM:\t\t%-.75s\n", image_address); + pos += snprintf(buf + pos, PAGE_SIZE - pos, + "\tVariant:\t%-.20s\n", image_address + + SMEM_IMAGE_VERSION_VARIANT_OFFSET); + pos += snprintf(buf + pos, PAGE_SIZE - pos, + "\tVersion:\t%-.32s\n\n", + image_address + SMEM_IMAGE_VERSION_OEM_OFFSET); + + image_address += SMEM_IMAGE_VERSION_SINGLE_BLOCK_SIZE; + } + + return pos; +} + +static struct device_attribute qcom_soc_attr_raw_version = + __ATTR(raw_version, S_IRUGO, qcom_get_raw_version, NULL); + +static struct device_attribute qcom_soc_attr_raw_id = + __ATTR(raw_id, S_IRUGO, qcom_get_raw_id, NULL); + +static struct device_attribute qcom_soc_attr_vendor = + __ATTR(vendor, S_IRUGO, qcom_get_vendor, NULL); + +static struct device_attribute qcom_soc_attr_build_id = + __ATTR(build_id, S_IRUGO, qcom_get_build_id, NULL); + +static struct device_attribute qcom_soc_attr_hw_platform = + __ATTR(hw_platform, S_IRUGO, qcom_get_hw_platform, NULL); + + +static struct device_attribute qcom_soc_attr_platform_version = + __ATTR(platform_version, S_IRUGO, + qcom_get_platform_version, NULL); + +static struct device_attribute qcom_soc_attr_accessory_chip = + __ATTR(accessory_chip, S_IRUGO, + qcom_get_accessory_chip, NULL); + +static struct device_attribute qcom_soc_attr_platform_subtype = + __ATTR(platform_subtype, S_IRUGO, + qcom_get_platform_subtype, NULL); + +/* Platform Subtype String is being deprecated. Use Platform + * Subtype ID instead. + */ +static struct device_attribute qcom_soc_attr_platform_subtype_id = + __ATTR(platform_subtype_id, S_IRUGO, + qcom_get_platform_subtype_id, NULL); + +static struct device_attribute qcom_soc_attr_foundry_id = + __ATTR(foundry_id, S_IRUGO, + qcom_get_foundry_id, NULL); + +static struct device_attribute qcom_soc_attr_serial_number = + __ATTR(serial_number, S_IRUGO, + qcom_get_serial_number, NULL); + +static struct device_attribute qcom_soc_attr_chip_family = + __ATTR(chip_family, S_IRUGO, + qcom_get_chip_family, NULL); + +static struct device_attribute qcom_soc_attr_raw_device_family = + __ATTR(raw_device_family, S_IRUGO, + qcom_get_raw_device_family, NULL); + +static struct device_attribute qcom_soc_attr_raw_device_number = + __ATTR(raw_device_number, S_IRUGO, + qcom_get_raw_device_number, NULL); + +static struct device_attribute qcom_soc_attr_pmic_model = + __ATTR(pmic_model, S_IRUGO, + qcom_get_pmic_model, NULL); + +static struct device_attribute qcom_soc_attr_pmic_die_revision = + __ATTR(pmic_die_revision, S_IRUGO, + qcom_get_pmic_die_revision, NULL); + +static struct device_attribute image_version = + __ATTR(image_version, S_IRUGO | S_IWUSR, + qcom_get_image_version, qcom_set_image_version); + +static struct device_attribute image_variant = + __ATTR(image_variant, S_IRUGO | S_IWUSR, + qcom_get_image_variant, qcom_set_image_variant); + +static struct device_attribute image_crm_version = + __ATTR(image_crm_version, S_IRUGO | S_IWUSR, + qcom_get_image_crm_version, qcom_set_image_crm_version); + +static struct device_attribute select_image = + __ATTR(select_image, S_IRUGO | S_IWUSR, + qcom_get_image_number, qcom_select_image); + +static struct device_attribute images = + __ATTR(images, S_IRUGO, qcom_get_images, NULL); + +static void * __init setup_dummy_socinfo(void) +{ + if (early_machine_is_apq8064()) { + dummy_socinfo.id = APQ_8064_ID; + strlcpy(dummy_socinfo.build_id, "apq8064", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_apq8084()) { + dummy_socinfo.id = APQ_8084_ID; + strlcpy(dummy_socinfo.build_id, "apq8084", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_msm8916()) { + dummy_socinfo.id = MSM_8916_ID; + strlcpy(dummy_socinfo.build_id, "msm8916", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_msm8660()) { + dummy_socinfo.id = MSM_8660A_ID; + strlcpy(dummy_socinfo.build_id, "msm8660", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_msm8960()) { + dummy_socinfo.id = MSM_8960_ID; + strlcpy(dummy_socinfo.build_id, "msm8960", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_msm8974()) { + dummy_socinfo.id = MSM_8974_ID; + strlcpy(dummy_socinfo.build_id, "msm8974", + sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_msm8996()) { + dummy_socinfo.id = MSM_8996_ID; + strlcpy(dummy_socinfo.build_id, "msm8996", + sizeof(dummy_socinfo.build_id)); + } + + strlcat(dummy_socinfo.build_id, "Dummy socinfo", + sizeof(dummy_socinfo.build_id)); + return (void *) &dummy_socinfo; +} + +static void socinfo_populate_sysfs_files(struct device *qcom_soc_device) +{ + device_create_file(qcom_soc_device, &qcom_soc_attr_vendor); + device_create_file(qcom_soc_device, &image_version); + device_create_file(qcom_soc_device, &image_variant); + device_create_file(qcom_soc_device, &image_crm_version); + device_create_file(qcom_soc_device, &select_image); + device_create_file(qcom_soc_device, &images); + + switch (socinfo_format) { + case SOCINFO_VERSION(0, 12): + device_create_file(qcom_soc_device, + &qcom_soc_attr_chip_family); + device_create_file(qcom_soc_device, + &qcom_soc_attr_raw_device_family); + device_create_file(qcom_soc_device, + &qcom_soc_attr_raw_device_number); + case SOCINFO_VERSION(0, 11): + case SOCINFO_VERSION(0, 10): + device_create_file(qcom_soc_device, + &qcom_soc_attr_serial_number); + case SOCINFO_VERSION(0, 9): + device_create_file(qcom_soc_device, + &qcom_soc_attr_foundry_id); + case SOCINFO_VERSION(0, 8): + case SOCINFO_VERSION(0, 7): + device_create_file(qcom_soc_device, + &qcom_soc_attr_pmic_model); + device_create_file(qcom_soc_device, + &qcom_soc_attr_pmic_die_revision); + case SOCINFO_VERSION(0, 6): + device_create_file(qcom_soc_device, + &qcom_soc_attr_platform_subtype); + device_create_file(qcom_soc_device, + &qcom_soc_attr_platform_subtype_id); + case SOCINFO_VERSION(0, 5): + device_create_file(qcom_soc_device, + &qcom_soc_attr_accessory_chip); + case SOCINFO_VERSION(0, 4): + device_create_file(qcom_soc_device, + &qcom_soc_attr_platform_version); + case SOCINFO_VERSION(0, 3): + device_create_file(qcom_soc_device, + &qcom_soc_attr_hw_platform); + case SOCINFO_VERSION(0, 2): + device_create_file(qcom_soc_device, + &qcom_soc_attr_raw_id); + device_create_file(qcom_soc_device, + &qcom_soc_attr_raw_version); + case SOCINFO_VERSION(0, 1): + device_create_file(qcom_soc_device, + &qcom_soc_attr_build_id); + break; + default: + pr_err("Unknown socinfo format: v%u.%u\n", + SOCINFO_VERSION_MAJOR(socinfo_format), + SOCINFO_VERSION_MINOR(socinfo_format)); + break; + } +} + +static void socinfo_populate(struct soc_device_attribute *soc_dev_attr) +{ + uint32_t soc_version = socinfo_get_version(); + + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", socinfo_get_id()); + soc_dev_attr->family = "Snapdragon"; + soc_dev_attr->machine = socinfo_get_id_string(); + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u.%u", + SOCINFO_VERSION_MAJOR(soc_version), + SOCINFO_VERSION_MINOR(soc_version)); + return; + +} + +static int socinfo_init_sysfs(void) +{ + struct device *qcom_soc_device; + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) { + pr_err("Soc Device alloc failed!\n"); + return -ENOMEM; + } + + socinfo_populate(soc_dev_attr); + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR_OR_NULL(soc_dev)) { + kfree(soc_dev_attr); + pr_err("Soc device register failed\n"); + return -EIO; + } + + qcom_soc_device = soc_device_to_device(soc_dev); + socinfo_populate_sysfs_files(qcom_soc_device); + return 0; +} + +static void socinfo_print(void) +{ + uint32_t f_maj = SOCINFO_VERSION_MAJOR(socinfo_format); + uint32_t f_min = SOCINFO_VERSION_MINOR(socinfo_format); + uint32_t v_maj = SOCINFO_VERSION_MAJOR(socinfo->v0_1.version); + uint32_t v_min = SOCINFO_VERSION_MINOR(socinfo->v0_1.version); + + switch (socinfo_format) { + case SOCINFO_VERSION(0, 1): + pr_info("v%u.%u, id=%u, ver=%u.%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min); + break; + case SOCINFO_VERSION(0, 2): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version); + break; + case SOCINFO_VERSION(0, 3): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u\n", + f_maj, f_min, socinfo->v0_1.id, + v_maj, v_min, socinfo->v0_2.raw_id, + socinfo->v0_2.raw_version, socinfo->v0_3.hw_platform); + break; + case SOCINFO_VERSION(0, 4): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version); + break; + case SOCINFO_VERSION(0, 5): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u accessory_chip=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip); + break; + case SOCINFO_VERSION(0, 6): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u accessory_chip=%u, hw_plat_subtype=%u\n", + f_maj, f_min, socinfo->v0_1.id, + v_maj, v_min, socinfo->v0_2.raw_id, + socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip, + socinfo->v0_6.hw_platform_subtype); + break; + case SOCINFO_VERSION(0, 7): + case SOCINFO_VERSION(0, 8): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip, + socinfo->v0_6.hw_platform_subtype, + socinfo->v0_7.pmic_model, + socinfo->v0_7.pmic_die_revision); + break; + case SOCINFO_VERSION(0, 9): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u foundry_id=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip, + socinfo->v0_6.hw_platform_subtype, + socinfo->v0_7.pmic_model, + socinfo->v0_7.pmic_die_revision, + socinfo->v0_9.foundry_id); + break; + case SOCINFO_VERSION(0, 10): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u, foundry_id=%u, serial_number=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip, + socinfo->v0_6.hw_platform_subtype, + socinfo->v0_7.pmic_model, + socinfo->v0_7.pmic_die_revision, + socinfo->v0_9.foundry_id, + socinfo->v0_10.serial_number); + break; + case SOCINFO_VERSION(0, 11): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u, accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u, foundry_id=%u, serial_number=%u num_pmics=%u\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip, + socinfo->v0_6.hw_platform_subtype, + socinfo->v0_7.pmic_model, + socinfo->v0_7.pmic_die_revision, + socinfo->v0_9.foundry_id, + socinfo->v0_10.serial_number, + socinfo->v0_11.num_pmics); + break; + case SOCINFO_VERSION(0, 12): + pr_info("v%u.%u, id=%u, ver=%u.%u, raw_id=%u, raw_ver=%u, hw_plat=%u, hw_plat_ver=%u accessory_chip=%u, hw_plat_subtype=%u, pmic_model=%u, pmic_die_revision=%u, foundry_id=%u, serial_number=%u, num_pmics=%u, chip_family=0x%x, raw_device_family=0x%x, raw_device_number=0x%x\n", + f_maj, f_min, socinfo->v0_1.id, v_maj, v_min, + socinfo->v0_2.raw_id, socinfo->v0_2.raw_version, + socinfo->v0_3.hw_platform, + socinfo->v0_4.platform_version, + socinfo->v0_5.accessory_chip, + socinfo->v0_6.hw_platform_subtype, + socinfo->v0_7.pmic_model, + socinfo->v0_7.pmic_die_revision, + socinfo->v0_9.foundry_id, + socinfo->v0_10.serial_number, + socinfo->v0_11.num_pmics, + socinfo->v0_12.chip_family, + socinfo->v0_12.raw_device_family, + socinfo->v0_12.raw_device_number); + break; + + default: + pr_err("Unknown format found: v%u.%u\n", f_maj, f_min); + break; + } +} + +static void socinfo_select_format(void) +{ + uint32_t f_maj = SOCINFO_VERSION_MAJOR(socinfo->v0_1.format); + uint32_t f_min = SOCINFO_VERSION_MINOR(socinfo->v0_1.format); + + if (f_maj != 0) { + pr_err("Unsupported format v%u.%u. Falling back to dummy values.\n", + f_maj, f_min); + socinfo = setup_dummy_socinfo(); + } + + if (socinfo->v0_1.format > MAX_SOCINFO_FORMAT) { + pr_warn("Unsupported format v%u.%u. Falling back to v%u.%u.\n", + f_maj, f_min, SOCINFO_VERSION_MAJOR(MAX_SOCINFO_FORMAT), + SOCINFO_VERSION_MINOR(MAX_SOCINFO_FORMAT)); + socinfo_format = MAX_SOCINFO_FORMAT; + } else { + socinfo_format = socinfo->v0_1.format; + } +} + +static int qcom_socinfo_probe(struct platform_device *pdev) +{ + size_t size; + + socinfo = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, + &size); + if (IS_ERR_OR_NULL(socinfo)) { + if (PTR_ERR(socinfo) == -EPROBE_DEFER) + return PTR_ERR(socinfo); + else { + dev_warn(&pdev->dev, + "Can't find SMEM_HW_SW_BUILD_ID; falling back on dummy values.\n"); + socinfo = setup_dummy_socinfo(); + } + } + + socinfo_select_format(); + + WARN(!socinfo_get_id(), "Unknown SOC ID!\n"); + + if (socinfo_get_id() >= ARRAY_SIZE(cpu_of_id)) + BUG_ON("New IDs added! ID => CPU mapping needs an update.\n"); + else + cur_cpu = cpu_of_id[socinfo->v0_1.id].generic_soc_type; + + socinfo_print(); + + socinfo_init_sysfs(); + + return 0; +} + +static const struct of_device_id qcom_socinfo_of_match[] = { + { .compatible = "qcom,socinfo" }, + {} +}; +MODULE_DEVICE_TABLE(of, qcom_socinfo_of_match); + +static struct platform_driver qcom_socinfo_driver = { + .probe = qcom_socinfo_probe, + .driver = { + .name = "qcom-socinfo", + .of_match_table = qcom_socinfo_of_match, + }, +}; +module_platform_driver(qcom_socinfo_driver); + diff --git a/include/linux/soc/qcom/socinfo.h b/include/linux/soc/qcom/socinfo.h new file mode 100644 index 0000000..17ca50a --- /dev/null +++ b/include/linux/soc/qcom/socinfo.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2009-2016, 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 + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef _ARCH_ARM_MACH_MSM_SOCINFO_H_ +#define _ARCH_ARM_MACH_MSM_SOCINFO_H_ + +#include +#include +#include +#include +#include + +#include +/* + * SOC version type with major number in the upper 16 bits and minor + * number in the lower 16 bits. For example: + * 1.0 -> 0x00010000 + * 2.3 -> 0x00020003 + */ +#define SOCINFO_VERSION_MAJOR(ver) (((ver) & 0xffff0000) >> 16) +#define SOCINFO_VERSION_MINOR(ver) ((ver) & 0x0000ffff) +#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff)) + +#ifdef CONFIG_OF +#define early_machine_is_apq8064() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,apq8064") +#define early_machine_is_apq8084() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,apq8084") +#define early_machine_is_msm8916() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8916") +#define early_machine_is_msm8660() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8660") +#define early_machine_is_msm8960() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8960") +#define early_machine_is_msm8974() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8974") +#define early_machine_is_msm8996() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8996") +#else +#define early_machine_is_apq8064() 0 +#define early_machine_is_apq8084() 0 +#define early_machine_is_msm8916() 0 +#define early_machine_is_msm8660() 0 +#define early_machine_is_msm8960() 0 +#define early_machine_is_msm8974() 0 +#define early_machine_is_msm8996() 0 +#endif + +#define PLATFORM_SUBTYPE_MDM 1 +#define PLATFORM_SUBTYPE_INTERPOSERV3 2 +#define PLATFORM_SUBTYPE_SGLTE 6 + +enum qcom_cpu { + MSM_CPU_UNKNOWN = 0, + MSM_CPU_8960, + MSM_CPU_8960AB, + MSM_CPU_8064, + MSM_CPU_8974, + MSM_CPU_8974PRO_AA, + MSM_CPU_8974PRO_AB, + MSM_CPU_8974PRO_AC, + MSM_CPU_8916, + MSM_CPU_8084, + MSM_CPU_8996 +}; + +enum qcom_cpu_id { + MSM_UNKNOWN_ID, + MSM_8960_ID = 87, + APQ_8064_ID = 109, + MSM_8660A_ID = 122, + MSM_8260A_ID, + APQ_8060A_ID, + MSM_8974_ID = 126, + MPQ_8064_ID = 130, + MSM_8960AB_ID = 138, + APQ_8060AB_ID, + MSM_8260AB_ID, + MSM_8660AB_ID, + APQ_8084_ID = 178, + APQ_8074_ID = 184, + MSM_8274_ID, + MSM_8674_ID, + MSM_8974PRO_ID = 194, + MSM_8916_ID = 206, + APQ_8074_AA_ID = 208, + APQ_8074_AB_ID, + APQ_8074PRO_ID, + MSM_8274_AA_ID, + MSM_8274_AB_ID, + MSM_8274PRO_ID, + MSM_8674_AA_ID, + MSM_8674_AB_ID, + MSM_8674PRO_ID, + MSM_8974_AA_ID, + MSM_8974_AB_ID, + MSM_8996_ID = 246, + APQ_8016_ID, + MSM_8216_ID, + MSM_8116_ID, + MSM_8616_ID, + APQ8096_ID = 291, + MSM_8996SG_ID = 305, + MSM_8996AU_ID = 310, + APQ_8096AU_ID, + APQ_8096SG_ID +}; + +struct qcom_soc_info { + enum qcom_cpu generic_soc_type; + char *soc_id_string; +}; + +enum qcom_pmic_model { + PMIC_MODEL_PM8058 = 13, + PMIC_MODEL_PM8028, + PMIC_MODEL_PM8901, + PMIC_MODEL_PM8027, + PMIC_MODEL_ISL_9519, + PMIC_MODEL_PM8921, + PMIC_MODEL_PM8018, + PMIC_MODEL_PM8015, + PMIC_MODEL_PM8014, + PMIC_MODEL_PM8821, + PMIC_MODEL_PM8038, + PMIC_MODEL_PM8922, + PMIC_MODEL_PM8917, + PMIC_MODEL_UNKNOWN = 0xFFFFFFFF +}; + +enum hw_platform_type { + HW_PLATFORM_UNKNOWN, + HW_PLATFORM_SURF, + HW_PLATFORM_FFA, + HW_PLATFORM_FLUID, + HW_PLATFORM_SVLTE_FFA, + HW_PLATFORM_SVLTE_SURF, + HW_PLATFORM_MTP_MDM = 7, + HW_PLATFORM_MTP, + HW_PLATFORM_LIQUID, + /* Dragonboard platform id is assigned as 10 in CDT */ + HW_PLATFORM_DRAGON, + HW_PLATFORM_QRD, + HW_PLATFORM_HRD = 13, + HW_PLATFORM_DTV, + HW_PLATFORM_RCM = 21, + HW_PLATFORM_STP = 23, + HW_PLATFORM_SBC, + HW_PLATFORM_INVALID +}; + +enum accessory_chip_type { + ACCESSORY_CHIP_UNKNOWN = 0, + ACCESSORY_CHIP_CHARM = 58 +}; + +enum qrd_platform_subtype { + PLATFORM_SUBTYPE_QRD, + PLATFORM_SUBTYPE_SKUAA, + PLATFORM_SUBTYPE_SKUF, + PLATFORM_SUBTYPE_SKUAB, + PLATFORM_SUBTYPE_SKUG = 0x5, + PLATFORM_SUBTYPE_QRD_INVALID +}; + +enum platform_subtype { + PLATFORM_SUBTYPE_UNKNOWN, + PLATFORM_SUBTYPE_CHARM, + PLATFORM_SUBTYPE_STRANGE, + PLATFORM_SUBTYPE_STRANGE_2A, + PLATFORM_SUBTYPE_INVALID +}; + +enum msm_cpu socinfo_get_msm_cpu(void); +uint32_t socinfo_get_id(void); +uint32_t socinfo_get_version(void); +uint32_t socinfo_get_raw_id(void); +char *socinfo_get_build_id(void); +uint32_t socinfo_get_platform_type(void); +uint32_t socinfo_get_platform_subtype(void); +uint32_t socinfo_get_platform_version(void); +uint32_t socinfo_get_serial_number(void); +enum qcom_pmic_model socinfo_get_pmic_model(void); +uint32_t socinfo_get_pmic_die_revision(void); +int __init socinfo_init(void) __must_check; + +#endif -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project