-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The Qualcomm socinfo driver exposes information about the SoC, its version and its serial number to user space. Tested-by: Vinod Koul <vkoul@kernel.org> Reviewed-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Imran Khan <kimran@codeaurora.org> [Bjorn: Extract code to platform_driver, split patch in multiple] Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org> [Vaishali: Simplify declarations, introduce qcom_socinfo struct, Fix memory leak, Remove extra code and Misc code refactoring] Signed-off-by: Vaishali Thakkar <vaishali.thakkar@linaro.org> Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
- Loading branch information
Imran Khan
authored and
Bjorn Andersson
committed
Aug 5, 2019
1 parent
f7ccc7a
commit efb448d
Showing
4 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copyright (c) 2009-2017, The Linux Foundation. All rights reserved. | ||
* Copyright (c) 2017-2019, Linaro Ltd. | ||
*/ | ||
|
||
#include <linux/err.h> | ||
#include <linux/module.h> | ||
#include <linux/platform_device.h> | ||
#include <linux/random.h> | ||
#include <linux/slab.h> | ||
#include <linux/soc/qcom/smem.h> | ||
#include <linux/string.h> | ||
#include <linux/sys_soc.h> | ||
#include <linux/types.h> | ||
|
||
/* | ||
* SoC version type with major number in the upper 16 bits and minor | ||
* number in the lower 16 bits. | ||
*/ | ||
#define SOCINFO_MAJOR(ver) (((ver) >> 16) & 0xffff) | ||
#define SOCINFO_MINOR(ver) ((ver) & 0xffff) | ||
|
||
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32 | ||
|
||
/* | ||
* SMEM item id, used to acquire handles to respective | ||
* SMEM region. | ||
*/ | ||
#define SMEM_HW_SW_BUILD_ID 137 | ||
|
||
/* Socinfo SMEM item structure */ | ||
struct socinfo { | ||
__le32 fmt; | ||
__le32 id; | ||
__le32 ver; | ||
char build_id[SMEM_SOCINFO_BUILD_ID_LENGTH]; | ||
/* Version 2 */ | ||
__le32 raw_id; | ||
__le32 raw_ver; | ||
/* Version 3 */ | ||
__le32 hw_plat; | ||
/* Version 4 */ | ||
__le32 plat_ver; | ||
/* Version 5 */ | ||
__le32 accessory_chip; | ||
/* Version 6 */ | ||
__le32 hw_plat_subtype; | ||
/* Version 7 */ | ||
__le32 pmic_model; | ||
__le32 pmic_die_rev; | ||
/* Version 8 */ | ||
__le32 pmic_model_1; | ||
__le32 pmic_die_rev_1; | ||
__le32 pmic_model_2; | ||
__le32 pmic_die_rev_2; | ||
/* Version 9 */ | ||
__le32 foundry_id; | ||
/* Version 10 */ | ||
__le32 serial_num; | ||
/* Version 11 */ | ||
__le32 num_pmics; | ||
__le32 pmic_array_offset; | ||
/* Version 12 */ | ||
__le32 chip_family; | ||
__le32 raw_device_family; | ||
__le32 raw_device_num; | ||
}; | ||
|
||
struct qcom_socinfo { | ||
struct soc_device *soc_dev; | ||
struct soc_device_attribute attr; | ||
}; | ||
|
||
struct soc_id { | ||
unsigned int id; | ||
const char *name; | ||
}; | ||
|
||
static const struct soc_id soc_id[] = { | ||
{ 87, "MSM8960" }, | ||
{ 109, "APQ8064" }, | ||
{ 122, "MSM8660A" }, | ||
{ 123, "MSM8260A" }, | ||
{ 124, "APQ8060A" }, | ||
{ 126, "MSM8974" }, | ||
{ 130, "MPQ8064" }, | ||
{ 138, "MSM8960AB" }, | ||
{ 139, "APQ8060AB" }, | ||
{ 140, "MSM8260AB" }, | ||
{ 141, "MSM8660AB" }, | ||
{ 178, "APQ8084" }, | ||
{ 184, "APQ8074" }, | ||
{ 185, "MSM8274" }, | ||
{ 186, "MSM8674" }, | ||
{ 194, "MSM8974PRO" }, | ||
{ 206, "MSM8916" }, | ||
{ 208, "APQ8074-AA" }, | ||
{ 209, "APQ8074-AB" }, | ||
{ 210, "APQ8074PRO" }, | ||
{ 211, "MSM8274-AA" }, | ||
{ 212, "MSM8274-AB" }, | ||
{ 213, "MSM8274PRO" }, | ||
{ 214, "MSM8674-AA" }, | ||
{ 215, "MSM8674-AB" }, | ||
{ 216, "MSM8674PRO" }, | ||
{ 217, "MSM8974-AA" }, | ||
{ 218, "MSM8974-AB" }, | ||
{ 246, "MSM8996" }, | ||
{ 247, "APQ8016" }, | ||
{ 248, "MSM8216" }, | ||
{ 249, "MSM8116" }, | ||
{ 250, "MSM8616" }, | ||
{ 291, "APQ8096" }, | ||
{ 305, "MSM8996SG" }, | ||
{ 310, "MSM8996AU" }, | ||
{ 311, "APQ8096AU" }, | ||
{ 312, "APQ8096SG" }, | ||
}; | ||
|
||
static const char *socinfo_machine(struct device *dev, unsigned int id) | ||
{ | ||
int idx; | ||
|
||
for (idx = 0; idx < ARRAY_SIZE(soc_id); idx++) { | ||
if (soc_id[idx].id == id) | ||
return soc_id[idx].name; | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
static int qcom_socinfo_probe(struct platform_device *pdev) | ||
{ | ||
struct qcom_socinfo *qs; | ||
struct socinfo *info; | ||
size_t item_size; | ||
|
||
info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, | ||
&item_size); | ||
if (IS_ERR(info)) { | ||
dev_err(&pdev->dev, "Couldn't find socinfo\n"); | ||
return PTR_ERR(info); | ||
} | ||
|
||
qs = devm_kzalloc(&pdev->dev, sizeof(*qs), GFP_KERNEL); | ||
if (!qs) | ||
return -ENOMEM; | ||
|
||
qs->attr.family = "Snapdragon"; | ||
qs->attr.machine = socinfo_machine(&pdev->dev, | ||
le32_to_cpu(info->id)); | ||
qs->attr.revision = devm_kasprintf(&pdev->dev, GFP_KERNEL, "%u.%u", | ||
SOCINFO_MAJOR(le32_to_cpu(info->ver)), | ||
SOCINFO_MINOR(le32_to_cpu(info->ver))); | ||
if (offsetof(struct socinfo, serial_num) <= item_size) | ||
qs->attr.serial_number = devm_kasprintf(&pdev->dev, GFP_KERNEL, | ||
"%u", | ||
le32_to_cpu(info->serial_num)); | ||
|
||
qs->soc_dev = soc_device_register(&qs->attr); | ||
if (IS_ERR(qs->soc_dev)) | ||
return PTR_ERR(qs->soc_dev); | ||
|
||
/* Feed the soc specific unique data into entropy pool */ | ||
add_device_randomness(info, item_size); | ||
|
||
platform_set_drvdata(pdev, qs->soc_dev); | ||
|
||
return 0; | ||
} | ||
|
||
static int qcom_socinfo_remove(struct platform_device *pdev) | ||
{ | ||
struct qcom_socinfo *qs = platform_get_drvdata(pdev); | ||
|
||
soc_device_unregister(qs->soc_dev); | ||
|
||
return 0; | ||
} | ||
|
||
static struct platform_driver qcom_socinfo_driver = { | ||
.probe = qcom_socinfo_probe, | ||
.remove = qcom_socinfo_remove, | ||
.driver = { | ||
.name = "qcom-socinfo", | ||
}, | ||
}; | ||
|
||
module_platform_driver(qcom_socinfo_driver); | ||
|
||
MODULE_DESCRIPTION("Qualcomm SoCinfo driver"); | ||
MODULE_LICENSE("GPL v2"); | ||
MODULE_ALIAS("platform:qcom-socinfo"); |