Qualcomm driver updates for v6.5

Konrad Dybcio is promoted, from reviewer, to co-maintainer.
 
 The mdt_loader gets a fix to the detection of split binaries, where the
 previous logic sometimes concluded that the first segments was not
 split, in a split image. The unconditional calling of
 scm_pas_mem_setup() turns out to cause a regression and is reverted.
 
 The altmode subfunction of pmic_glink is enabled for SM8450.
 
 A new driver for exposing power statistics from the RPM, for debugging
 purposes, is introduced.
 
 OCMEM gets a debug prints of the hardware version, QMI helpers are
 transitioned to alloc_ordered_workqueue() and an error message in
 ramp_controller is improved.
 
 An API is introduced to the SMEM driver to allow other drivers to query
 the SoC id, rather than open-coding the parsing of the relevant SMEM
 item. This is then used to clean up the Qualcomm NVMEM-based cpufreq
 driver.
 
 Socinfo is extended with knowledge about IPQ5018, IPQ5312 and IPQ5302.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCAAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmSFHJsVHGFuZGVyc3Nv
 bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3FrtoQAMUN2gF5ZP3rlSEkQbKNMDhNHXVw
 S8AexPk6Qw8BcEBOD4YPqrmfrMvNP7Bqh3QkfS/7m5vx0o8bUOw+Xz+C4+9LSUD7
 /qW29GlQllwMuRNOdH3J/nYXwpV5WJyiSF/jXy0/GRbz+D/XYSNDC57z/lXTcKKq
 dYJrKxms6EF4AgHe88V0bmk6/V4xfa5p6xW3pCG7GLqNHOvhZ16oUmoPiZGVpQMk
 go/HsoIB00HktKflTLOUXJWD6qVOVNCaQQEarx+zY1txfmvpVGL+PO6Eaxt00Sa4
 pHRvB0CIZPNvdDWELfsfRx6DbPBJRGBlneag04BI918fx4X+jn4uP+1jzw9am03U
 M78k0LGBY23Psy6KhoMu5MM4Cntt3kTQ0SwHl/xayzTrAhK2xdmd1bo67ArRl+HX
 OZrZ7Se3Cm16CAWqsW42so6MJeDllc8d/ahN/e2NwsNy1lhosK06jRJEdh3N238D
 ouL56HoxrweYB0kbK4TkPLewrLZC7DYnr0KMVsPhsSraeJBaBPOVZDhuNSUXXMtf
 WdyCRMMxKU3OweLcJiKuGFzNqr2963341Y6NlD+tf1Uy5IEnbIp4jFi9BsJBNVZt
 NucOXJYm5OJeAHp8BcMFbnL8uA1NqEYQXwezodPSIGqHzxBtGf6f0hALsIpiUQnA
 GLDp99yVujEN2dsE
 =9Fv4
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEiK/NIGsWEZVxh/FrYKtH/8kJUicFAmSTVmkACgkQYKtH/8kJ
 Uid08g//b5kJZnsiWA43LrkblMSEdZoeijrn+x2NU95YQ4s/oz2RnUtgNCGDhM84
 Fi60PzU5L1JVj6GVeL51J5jlBGKzGqe4FfPTN4aPlSV4Z0B3cuevgWmHnw4Mh/zj
 t/1b5QVVZxbKKxb8MP+U2iAvyxVwIhIA4zehh0+XGagV3qquURO7QLtLUg42Yx51
 HFLADq2JI8trm+CjjCNBv9mq7EipC/g0nbsCs98nxl/sPC7PqtNxL6BXCuz3a8BX
 JvA1LVRP2JYkQfb6SMnTFiqkT6LdB7bt6oXZdnwnsNTI1nhFqbMJRMsToWb3HEvv
 9lprraDpaufbzvB1b+x8Aar4OmbbWaY2ZpNJqqzCM5eVW2Zs/p5J+ZfOYVigtQYO
 qIQvENv+eKETu4nVvdlf72FPAVe+GXnVAcl3LEwhMUxYcRMha4JT0i8mndnCzpT+
 tZLdkBMp/t7rZPIa7D+07Xmorefw9e9rwynQg2C2yw3AV5v7j09dPJDFITFcF6Yl
 7ADtoy7zHTTv6/0n04RfPC9jPMoi8RbPoVNMVAWW7t7S0984o3gqWXJPLWJdTzA/
 ODOupqmvSpZld1rUklKKH/dY/Ha7iUTSci7rZrXSafXR8LBEn2FO6ehZqUvk7T/u
 qM3rs5wacHP2OcNDtwHHJoyfHXpxaQ2JqVOcUNkcdcwhN9dbdxA=
 =4/0b
 -----END PGP SIGNATURE-----

Merge tag 'qcom-drivers-for-6.5' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into soc/drivers

Qualcomm driver updates for v6.5

Konrad Dybcio is promoted, from reviewer, to co-maintainer.

The mdt_loader gets a fix to the detection of split binaries, where the
previous logic sometimes concluded that the first segments was not
split, in a split image. The unconditional calling of
scm_pas_mem_setup() turns out to cause a regression and is reverted.

The altmode subfunction of pmic_glink is enabled for SM8450.

A new driver for exposing power statistics from the RPM, for debugging
purposes, is introduced.

OCMEM gets a debug prints of the hardware version, QMI helpers are
transitioned to alloc_ordered_workqueue() and an error message in
ramp_controller is improved.

An API is introduced to the SMEM driver to allow other drivers to query
the SoC id, rather than open-coding the parsing of the relevant SMEM
item. This is then used to clean up the Qualcomm NVMEM-based cpufreq
driver.

Socinfo is extended with knowledge about IPQ5018, IPQ5312 and IPQ5302.

* tag 'qcom-drivers-for-6.5' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (23 commits)
  soc: qcom: ocmem: Add OCMEM hardware version print
  cpufreq: qcom-nvmem: use helper to get SMEM SoC ID
  cpufreq: qcom-nvmem: use SoC ID-s from bindings
  soc: qcom: smem: introduce qcom_smem_get_soc_id()
  soc: qcom: smem: Switch to EXPORT_SYMBOL_GPL()
  soc: qcom: socinfo: move SMEM item struct and defines to a header
  soc: qcom: mdt_loader: Fix unconditional call to scm_pas_mem_setup
  MAINTAINERS: Add Konrad Dybcio as linux-arm-msm co-maintainer
  dt-bindings: sram: qcom,imem: Document MSM8226
  soc: qcom: socinfo: Add Soc ID for IPQ5312 and IPQ5302
  dt-bindings: arm: qcom,ids: add SoC ID for IPQ5312 and IPQ5302
  soc: qcom: socinfo: Add IDs for IPQ5018 family
  dt-bindings: arm: qcom,ids: Add IDs for IPQ5018 family
  soc: qcom: Introduce RPM master stats driver
  dt-bindings: soc: qcom: Add RPM Master stats
  soc: qcom: qmi: Use alloc_ordered_workqueue() to create ordered workqueues
  soc: qcom: ramp_controller: Improve error message for failure in .remove()
  dt-bindings: soc: qcom: smd-rpm: allow MSM8226 over SMD
  soc: qcom: rpmpd: use correct __le32 type
  dt-bindings: soc: qcom: eud: Fix compatible string in the example
  ...

Link: https://lore.kernel.org/r/20230611010044.2481875-1-andersson@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2023-06-21 21:58:32 +02:00
commit a08000d5e0
21 changed files with 442 additions and 140 deletions

View File

@ -26,6 +26,7 @@ properties:
items:
- enum:
- qcom,qdu1000-aoss-qmp
- qcom,sa8775p-aoss-qmp
- qcom,sc7180-aoss-qmp
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp

View File

@ -55,9 +55,10 @@ additionalProperties: false
examples:
- |
eud@88e0000 {
compatible = "qcom,sc7280-eud","qcom,eud";
compatible = "qcom,sc7280-eud", "qcom,eud";
reg = <0x88e0000 0x2000>,
<0x88e2000 0x1000>;
ports {
#address-cells = <1>;
#size-cells = <0>;
@ -67,6 +68,7 @@ examples:
remote-endpoint = <&usb2_role_switch>;
};
};
port@1 {
reg = <1>;
eud_con: endpoint {

View File

@ -0,0 +1,69 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,rpm-master-stats.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. (QTI) RPM Master Stats
maintainers:
- Konrad Dybcio <konrad.dybcio@linaro.org>
description: |
The Qualcomm RPM (Resource Power Manager) architecture includes a concept
of "RPM Masters". They can be thought of as "the local gang leaders", usually
spanning a single subsystem (e.g. APSS, ADSP, CDSP). All of the RPM decisions
(particularly around entering hardware-driven low power modes: XO shutdown
and total system-wide power collapse) are first made at Master-level, and
only then aggregated for the entire system.
The Master Stats provide a few useful bits that can be used to assess whether
our device has entered the desired low-power mode, how long it took to do so,
the duration of that residence, how long it took to come back online,
how many times a given sleep state was entered and which cores are actively
voting for staying awake.
This scheme has been used on various SoCs in the 2013-2023 era, with some
newer or higher-end designs providing this information through an SMEM query.
properties:
compatible:
const: qcom,rpm-master-stats
qcom,rpm-msg-ram:
$ref: /schemas/types.yaml#/definitions/phandle-array
description: Phandle to an RPM MSG RAM slice containing the master stats
minItems: 1
maxItems: 5
qcom,master-names:
$ref: /schemas/types.yaml#/definitions/string-array
description:
The name of the RPM Master which owns the MSG RAM slice where this
instance of Master Stats resides
minItems: 1
maxItems: 5
required:
- compatible
- qcom,rpm-msg-ram
- qcom,master-names
additionalProperties: false
examples:
- |
stats {
compatible = "qcom,rpm-master-stats";
qcom,rpm-msg-ram = <&apss_master_stats>,
<&mpss_master_stats>,
<&adsp_master_stats>,
<&cdsp_master_stats>,
<&tz_master_stats>;
qcom,master-names = "APSS",
"MPSS",
"ADSP",
"CDSP",
"TZ";
};
...

View File

@ -81,6 +81,7 @@ if:
contains:
enum:
- qcom,rpm-apq8084
- qcom,rpm-msm8226
- qcom,rpm-msm8916
- qcom,rpm-msm8936
- qcom,rpm-msm8974

View File

@ -18,6 +18,7 @@ properties:
items:
- enum:
- qcom,apq8064-imem
- qcom,msm8226-imem
- qcom,msm8974-imem
- qcom,qcs404-imem
- qcom,sc7180-imem

View File

@ -2566,7 +2566,7 @@ F: arch/arm64/boot/dts/qcom/sdm845-cheza*
ARM/QUALCOMM SUPPORT
M: Andy Gross <agross@kernel.org>
M: Bjorn Andersson <andersson@kernel.org>
R: Konrad Dybcio <konrad.dybcio@linaro.org>
M: Konrad Dybcio <konrad.dybcio@linaro.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git

View File

@ -29,20 +29,7 @@
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
#define MSM_ID_SMEM 137
enum _msm_id {
MSM8996V3 = 0xF6ul,
APQ8096V3 = 0x123ul,
MSM8996SG = 0x131ul,
APQ8096SG = 0x138ul,
};
enum _msm8996_version {
MSM8996_V3,
MSM8996_SG,
NUM_OF_MSM8996_VERSIONS,
};
#include <dt-bindings/arm/qcom,ids.h>
struct qcom_cpufreq_drv;
@ -140,60 +127,32 @@ static void get_krait_bin_format_b(struct device *cpu_dev,
dev_dbg(cpu_dev, "PVS version: %d\n", *pvs_ver);
}
static enum _msm8996_version qcom_cpufreq_get_msm_id(void)
{
size_t len;
u32 *msm_id;
enum _msm8996_version version;
msm_id = qcom_smem_get(QCOM_SMEM_HOST_ANY, MSM_ID_SMEM, &len);
if (IS_ERR(msm_id))
return NUM_OF_MSM8996_VERSIONS;
/* The first 4 bytes are format, next to them is the actual msm-id */
msm_id++;
switch ((enum _msm_id)*msm_id) {
case MSM8996V3:
case APQ8096V3:
version = MSM8996_V3;
break;
case MSM8996SG:
case APQ8096SG:
version = MSM8996_SG;
break;
default:
version = NUM_OF_MSM8996_VERSIONS;
}
return version;
}
static int qcom_cpufreq_kryo_name_version(struct device *cpu_dev,
struct nvmem_cell *speedbin_nvmem,
char **pvs_name,
struct qcom_cpufreq_drv *drv)
{
size_t len;
u32 msm_id;
u8 *speedbin;
enum _msm8996_version msm8996_version;
int ret;
*pvs_name = NULL;
msm8996_version = qcom_cpufreq_get_msm_id();
if (NUM_OF_MSM8996_VERSIONS == msm8996_version) {
dev_err(cpu_dev, "Not Snapdragon 820/821!");
return -ENODEV;
}
ret = qcom_smem_get_soc_id(&msm_id);
if (ret)
return ret;
speedbin = nvmem_cell_read(speedbin_nvmem, &len);
if (IS_ERR(speedbin))
return PTR_ERR(speedbin);
switch (msm8996_version) {
case MSM8996_V3:
switch (msm_id) {
case QCOM_ID_MSM8996:
case QCOM_ID_APQ8096:
drv->versions = 1 << (unsigned int)(*speedbin);
break;
case MSM8996_SG:
case QCOM_ID_MSM8996SG:
case QCOM_ID_APQ8096SG:
drv->versions = 1 << ((unsigned int)(*speedbin) + 4);
break;
default:

View File

@ -135,6 +135,17 @@ config QCOM_RMTFS_MEM
Say y here if you intend to boot the modem remoteproc.
config QCOM_RPM_MASTER_STATS
tristate "Qualcomm RPM Master stats"
depends on ARCH_QCOM || COMPILE_TEST
help
The RPM Master sleep stats driver provides detailed per-subsystem
sleep/wake data, read from the RPM message RAM. It can be used to
assess whether all the low-power modes available are entered as
expected or to check which part of the SoC prevents it from sleeping.
Say y here if you intend to debug or monitor platform sleep.
config QCOM_RPMH
tristate "Qualcomm RPM-Hardened (RPMH) Communication"
depends on ARCH_QCOM || COMPILE_TEST

View File

@ -14,6 +14,7 @@ obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
qmi_helpers-y += qmi_encdec.o qmi_interface.o
obj-$(CONFIG_QCOM_RAMP_CTRL) += ramp_controller.o
obj-$(CONFIG_QCOM_RMTFS_MEM) += rmtfs_mem.o
obj-$(CONFIG_QCOM_RPM_MASTER_STATS) += rpm_master_stats.o
obj-$(CONFIG_QCOM_RPMH) += qcom_rpmh.o
qcom_rpmh-y += rpmh-rsc.o
qcom_rpmh-y += rpmh.o

View File

@ -210,6 +210,7 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
const struct elf32_hdr *ehdr;
phys_addr_t min_addr = PHYS_ADDR_MAX;
phys_addr_t max_addr = 0;
bool relocate = false;
size_t metadata_len;
void *metadata;
int ret;
@ -224,6 +225,9 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
if (!mdt_phdr_valid(phdr))
continue;
if (phdr->p_flags & QCOM_MDT_RELOCATABLE)
relocate = true;
if (phdr->p_paddr < min_addr)
min_addr = phdr->p_paddr;
@ -246,11 +250,13 @@ int qcom_mdt_pas_init(struct device *dev, const struct firmware *fw,
goto out;
}
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
if (ret) {
/* Unable to set up relocation */
dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
goto out;
if (relocate) {
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys, max_addr - min_addr);
if (ret) {
/* Unable to set up relocation */
dev_err(dev, "error %d setting up firmware %s\n", ret, fw_name);
goto out;
}
}
out:
@ -258,6 +264,26 @@ out:
}
EXPORT_SYMBOL_GPL(qcom_mdt_pas_init);
static bool qcom_mdt_bins_are_split(const struct firmware *fw, const char *fw_name)
{
const struct elf32_phdr *phdrs;
const struct elf32_hdr *ehdr;
uint64_t seg_start, seg_end;
int i;
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
for (i = 0; i < ehdr->e_phnum; i++) {
seg_start = phdrs[i].p_offset;
seg_end = phdrs[i].p_offset + phdrs[i].p_filesz;
if (seg_start > fw->size || seg_end > fw->size)
return true;
}
return false;
}
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
@ -270,6 +296,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
phys_addr_t min_addr = PHYS_ADDR_MAX;
ssize_t offset;
bool relocate = false;
bool is_split;
void *ptr;
int ret = 0;
int i;
@ -277,6 +304,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (!fw || !mem_region || !mem_phys || !mem_size)
return -EINVAL;
is_split = qcom_mdt_bins_are_split(fw, fw_name);
ehdr = (struct elf32_hdr *)fw->data;
phdrs = (struct elf32_phdr *)(ehdr + 1);
@ -330,8 +358,7 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ptr = mem_region + offset;
if (phdr->p_filesz && phdr->p_offset < fw->size &&
phdr->p_offset + phdr->p_filesz <= fw->size) {
if (phdr->p_filesz && !is_split) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
dev_err(dev, "file %s segment %d would be truncated\n",

View File

@ -76,6 +76,10 @@ struct ocmem {
#define OCMEM_REG_GFX_MPU_START 0x00001004
#define OCMEM_REG_GFX_MPU_END 0x00001008
#define OCMEM_HW_VERSION_MAJOR(val) FIELD_GET(GENMASK(31, 28), val)
#define OCMEM_HW_VERSION_MINOR(val) FIELD_GET(GENMASK(27, 16), val)
#define OCMEM_HW_VERSION_STEP(val) FIELD_GET(GENMASK(15, 0), val)
#define OCMEM_HW_PROFILE_NUM_PORTS(val) FIELD_PREP(0x0000000f, (val))
#define OCMEM_HW_PROFILE_NUM_MACROS(val) FIELD_PREP(0x00003f00, (val))
@ -355,6 +359,12 @@ static int ocmem_dev_probe(struct platform_device *pdev)
}
}
reg = ocmem_read(ocmem, OCMEM_REG_HW_VERSION);
dev_dbg(dev, "OCMEM hardware version: %lu.%lu.%lu\n",
OCMEM_HW_VERSION_MAJOR(reg),
OCMEM_HW_VERSION_MINOR(reg),
OCMEM_HW_VERSION_STEP(reg));
reg = ocmem_read(ocmem, OCMEM_REG_HW_PROFILE);
ocmem->num_ports = OCMEM_HW_PROFILE_NUM_PORTS(reg);
ocmem->num_macros = OCMEM_HW_PROFILE_NUM_MACROS(reg);

View File

@ -338,13 +338,17 @@ static int pmic_glink_remove(struct platform_device *pdev)
return 0;
}
/* Do not handle altmode for now on those platforms */
static const unsigned long pmic_glink_sm8450_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_ALTMODE) |
BIT(PMIC_GLINK_CLIENT_UCSI);
/* Do not handle altmode for now on those platforms */
static const unsigned long pmic_glink_sm8550_client_mask = BIT(PMIC_GLINK_CLIENT_BATT) |
BIT(PMIC_GLINK_CLIENT_UCSI);
static const struct of_device_id pmic_glink_of_match[] = {
{ .compatible = "qcom,sm8450-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
{ .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8450_client_mask },
{ .compatible = "qcom,sm8550-pmic-glink", .data = &pmic_glink_sm8550_client_mask },
{ .compatible = "qcom,pmic-glink" },
{}
};

View File

@ -650,7 +650,7 @@ int qmi_handle_init(struct qmi_handle *qmi, size_t recv_buf_size,
if (!qmi->recv_buf)
return -ENOMEM;
qmi->wq = alloc_workqueue("qmi_msg_handler", WQ_UNBOUND, 1);
qmi->wq = alloc_ordered_workqueue("qmi_msg_handler", 0);
if (!qmi->wq) {
ret = -ENOMEM;
goto err_free_recv_buf;

View File

@ -308,12 +308,15 @@ static int qcom_ramp_controller_probe(struct platform_device *pdev)
return qcom_ramp_controller_start(qrc);
}
static int qcom_ramp_controller_remove(struct platform_device *pdev)
static void qcom_ramp_controller_remove(struct platform_device *pdev)
{
struct qcom_ramp_controller *qrc = platform_get_drvdata(pdev);
int ret;
return rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis,
RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis);
ret = rc_write_cfg(qrc, qrc->desc->cfg_ramp_dis,
RC_DCVS_CFG_SID, qrc->desc->num_ramp_dis);
if (ret)
dev_err(&pdev->dev, "Failed to send disable sequence\n");
}
static const struct of_device_id qcom_ramp_controller_match_table[] = {
@ -329,7 +332,7 @@ static struct platform_driver qcom_ramp_controller_driver = {
.suppress_bind_attrs = true,
},
.probe = qcom_ramp_controller_probe,
.remove = qcom_ramp_controller_remove,
.remove_new = qcom_ramp_controller_remove,
};
static int __init qcom_ramp_controller_init(void)

View File

@ -0,0 +1,163 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
* Copyright (c) 2023, Linaro Limited
*
* This driver supports what is known as "Master Stats v2" in Qualcomm
* downstream kernel terms, which seems to be the only version which has
* ever shipped, all the way from 2013 to 2023.
*/
#include <linux/debugfs.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
struct master_stats_data {
void __iomem *base;
const char *label;
};
struct rpm_master_stats {
u32 active_cores;
u32 num_shutdowns;
u64 shutdown_req;
u64 wakeup_idx;
u64 bringup_req;
u64 bringup_ack;
u32 wakeup_reason; /* 0 = "rude wakeup", 1 = scheduled wakeup */
u32 last_sleep_trans_dur;
u32 last_wake_trans_dur;
/* Per-subsystem (*not necessarily* SoC-wide) XO shutdown stats */
u32 xo_count;
u64 xo_last_enter;
u64 last_exit;
u64 xo_total_dur;
} __packed;
static int master_stats_show(struct seq_file *s, void *unused)
{
struct master_stats_data *data = s->private;
struct rpm_master_stats stat;
memcpy_fromio(&stat, data->base, sizeof(stat));
seq_printf(s, "%s:\n", data->label);
seq_printf(s, "\tLast shutdown @ %llu\n", stat.shutdown_req);
seq_printf(s, "\tLast bringup req @ %llu\n", stat.bringup_req);
seq_printf(s, "\tLast bringup ack @ %llu\n", stat.bringup_ack);
seq_printf(s, "\tLast wakeup idx: %llu\n", stat.wakeup_idx);
seq_printf(s, "\tLast XO shutdown enter @ %llu\n", stat.xo_last_enter);
seq_printf(s, "\tLast XO shutdown exit @ %llu\n", stat.last_exit);
seq_printf(s, "\tXO total duration: %llu\n", stat.xo_total_dur);
seq_printf(s, "\tLast sleep transition duration: %u\n", stat.last_sleep_trans_dur);
seq_printf(s, "\tLast wake transition duration: %u\n", stat.last_wake_trans_dur);
seq_printf(s, "\tXO shutdown count: %u\n", stat.xo_count);
seq_printf(s, "\tWakeup reason: 0x%x\n", stat.wakeup_reason);
seq_printf(s, "\tShutdown count: %u\n", stat.num_shutdowns);
seq_printf(s, "\tActive cores bitmask: 0x%x\n", stat.active_cores);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(master_stats);
static int master_stats_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct master_stats_data *data;
struct device_node *msgram_np;
struct dentry *dent, *root;
struct resource res;
int count, i, ret;
count = of_property_count_strings(dev->of_node, "qcom,master-names");
if (count < 0)
return count;
data = devm_kzalloc(dev, count * sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
root = debugfs_create_dir("qcom_rpm_master_stats", NULL);
platform_set_drvdata(pdev, root);
for (i = 0; i < count; i++) {
msgram_np = of_parse_phandle(dev->of_node, "qcom,rpm-msg-ram", i);
if (!msgram_np) {
debugfs_remove_recursive(root);
return dev_err_probe(dev, -ENODEV,
"Couldn't parse MSG RAM phandle idx %d", i);
}
/*
* Purposefully skip devm_platform helpers as we're using a
* shared resource.
*/
ret = of_address_to_resource(msgram_np, 0, &res);
of_node_put(msgram_np);
if (ret < 0) {
debugfs_remove_recursive(root);
return ret;
}
data[i].base = devm_ioremap(dev, res.start, resource_size(&res));
if (IS_ERR(data[i].base)) {
debugfs_remove_recursive(root);
return dev_err_probe(dev, -EINVAL,
"Could not map the MSG RAM slice idx %d!\n", i);
}
ret = of_property_read_string_index(dev->of_node, "qcom,master-names", i,
&data[i].label);
if (ret < 0) {
debugfs_remove_recursive(root);
return dev_err_probe(dev, ret,
"Could not read name idx %d!\n", i);
}
/*
* Generally it's not advised to fail on debugfs errors, but this
* driver's only job is exposing data therein.
*/
dent = debugfs_create_file(data[i].label, 0444, root,
&data[i], &master_stats_fops);
if (IS_ERR(dent)) {
debugfs_remove_recursive(root);
return dev_err_probe(dev, PTR_ERR(dent),
"Failed to create debugfs file %s!\n", data[i].label);
}
}
device_set_pm_not_required(dev);
return 0;
}
static void master_stats_remove(struct platform_device *pdev)
{
struct dentry *root = platform_get_drvdata(pdev);
debugfs_remove_recursive(root);
}
static const struct of_device_id rpm_master_table[] = {
{ .compatible = "qcom,rpm-master-stats" },
{ },
};
static struct platform_driver master_stats_driver = {
.probe = master_stats_probe,
.remove_new = master_stats_remove,
.driver = {
.name = "qcom_rpm_master_stats",
.of_match_table = rpm_master_table,
},
};
module_platform_driver(master_stats_driver);
MODULE_DESCRIPTION("Qualcomm RPM Master Statistics driver");
MODULE_LICENSE("GPL");

View File

@ -892,8 +892,8 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain,
pd->corner = state;
/* Always send updates for vfc and vfl */
if (!pd->enabled && pd->key != KEY_FLOOR_CORNER &&
pd->key != KEY_FLOOR_LEVEL)
if (!pd->enabled && pd->key != cpu_to_le32(KEY_FLOOR_CORNER) &&
pd->key != cpu_to_le32(KEY_FLOOR_LEVEL))
goto out;
ret = rpmpd_aggregate_corner(pd);

View File

@ -14,6 +14,7 @@
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/socinfo.h>
/*
* The Qualcomm shared memory system is a allocate only heap structure that
@ -500,7 +501,7 @@ int qcom_smem_alloc(unsigned host, unsigned item, size_t size)
return ret;
}
EXPORT_SYMBOL(qcom_smem_alloc);
EXPORT_SYMBOL_GPL(qcom_smem_alloc);
static void *qcom_smem_get_global(struct qcom_smem *smem,
unsigned item,
@ -674,7 +675,7 @@ void *qcom_smem_get(unsigned host, unsigned item, size_t *size)
return ptr;
}
EXPORT_SYMBOL(qcom_smem_get);
EXPORT_SYMBOL_GPL(qcom_smem_get);
/**
* qcom_smem_get_free_space() - retrieve amount of free space in a partition
@ -719,7 +720,7 @@ int qcom_smem_get_free_space(unsigned host)
return ret;
}
EXPORT_SYMBOL(qcom_smem_get_free_space);
EXPORT_SYMBOL_GPL(qcom_smem_get_free_space);
static bool addr_in_range(void __iomem *base, size_t size, void *addr)
{
@ -770,7 +771,29 @@ phys_addr_t qcom_smem_virt_to_phys(void *p)
return 0;
}
EXPORT_SYMBOL(qcom_smem_virt_to_phys);
EXPORT_SYMBOL_GPL(qcom_smem_virt_to_phys);
/**
* qcom_smem_get_soc_id() - return the SoC ID
* @id: On success, we return the SoC ID here.
*
* Look up SoC ID from HW/SW build ID and return it.
*
* Return: 0 on success, negative errno on failure.
*/
int qcom_smem_get_soc_id(u32 *id)
{
struct socinfo *info;
info = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_HW_SW_BUILD_ID, NULL);
if (IS_ERR(info))
return PTR_ERR(info);
*id = __le32_to_cpu(info->id);
return 0;
}
EXPORT_SYMBOL_GPL(qcom_smem_get_soc_id);
static int qcom_smem_get_sbl_version(struct qcom_smem *smem)
{

View File

@ -11,6 +11,7 @@
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
#include <linux/soc/qcom/socinfo.h>
#include <linux/string.h>
#include <linux/stringify.h>
#include <linux/sys_soc.h>
@ -32,15 +33,6 @@
#define qcom_board_id(id) QCOM_ID_ ## id, __stringify(id)
#define qcom_board_id_named(id, name) QCOM_ID_ ## id, (name)
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
/*
* SMEM item id, used to acquire handles to respective
* SMEM region.
*/
#define SMEM_HW_SW_BUILD_ID 137
#ifdef CONFIG_DEBUG_FS
#define SMEM_IMAGE_VERSION_BLOCKS_COUNT 32
#define SMEM_IMAGE_VERSION_SIZE 4096
@ -126,64 +118,7 @@ static const char *const pmic_models[] = {
[58] = "PM8450",
[65] = "PM8010",
};
#endif /* CONFIG_DEBUG_FS */
/* 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;
/* Version 13 */
__le32 nproduct_id;
char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
/* Version 14 */
__le32 num_clusters;
__le32 ncluster_array_offset;
__le32 num_defective_parts;
__le32 ndefective_parts_array_offset;
/* Version 15 */
__le32 nmodem_supported;
/* Version 16 */
__le32 feature_code;
__le32 pcode;
__le32 npartnamemap_offset;
__le32 nnum_partname_mapping;
/* Version 17 */
__le32 oem_variant;
};
#ifdef CONFIG_DEBUG_FS
struct socinfo_params {
u32 raw_device_family;
u32 hw_plat_subtype;
@ -434,6 +369,9 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SM8350) },
{ qcom_board_id(QCM2290) },
{ qcom_board_id(SM6115) },
{ qcom_board_id(IPQ5010) },
{ qcom_board_id(IPQ5018) },
{ qcom_board_id(IPQ5028) },
{ qcom_board_id(SC8280XP) },
{ qcom_board_id(IPQ6005) },
{ qcom_board_id(QRB5165) },
@ -447,6 +385,9 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id_named(SM8450_3, "SM8450") },
{ qcom_board_id(SC7280) },
{ qcom_board_id(SC7180P) },
{ qcom_board_id(IPQ5000) },
{ qcom_board_id(IPQ0509) },
{ qcom_board_id(IPQ0518) },
{ qcom_board_id(SM6375) },
{ qcom_board_id(IPQ9514) },
{ qcom_board_id(IPQ9550) },
@ -454,6 +395,7 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(IPQ9570) },
{ qcom_board_id(IPQ9574) },
{ qcom_board_id(SM8550) },
{ qcom_board_id(IPQ5016) },
{ qcom_board_id(IPQ9510) },
{ qcom_board_id(QRB4210) },
{ qcom_board_id(QRB2210) },
@ -461,11 +403,14 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QRU1000) },
{ qcom_board_id(QDU1000) },
{ qcom_board_id(QDU1010) },
{ qcom_board_id(IPQ5019) },
{ qcom_board_id(QRU1032) },
{ qcom_board_id(QRU1052) },
{ qcom_board_id(QRU1062) },
{ qcom_board_id(IPQ5332) },
{ qcom_board_id(IPQ5322) },
{ qcom_board_id(IPQ5312) },
{ qcom_board_id(IPQ5302) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)

View File

@ -216,6 +216,9 @@
#define QCOM_ID_SM8350 439
#define QCOM_ID_QCM2290 441
#define QCOM_ID_SM6115 444
#define QCOM_ID_IPQ5010 446
#define QCOM_ID_IPQ5018 447
#define QCOM_ID_IPQ5028 448
#define QCOM_ID_SC8280XP 449
#define QCOM_ID_IPQ6005 453
#define QCOM_ID_QRB5165 455
@ -229,6 +232,9 @@
#define QCOM_ID_SM8450_3 482
#define QCOM_ID_SC7280 487
#define QCOM_ID_SC7180P 495
#define QCOM_ID_IPQ5000 503
#define QCOM_ID_IPQ0509 504
#define QCOM_ID_IPQ0518 505
#define QCOM_ID_SM6375 507
#define QCOM_ID_IPQ9514 510
#define QCOM_ID_IPQ9550 511
@ -236,6 +242,7 @@
#define QCOM_ID_IPQ9570 513
#define QCOM_ID_IPQ9574 514
#define QCOM_ID_SM8550 519
#define QCOM_ID_IPQ5016 520
#define QCOM_ID_IPQ9510 521
#define QCOM_ID_QRB4210 523
#define QCOM_ID_QRB2210 524
@ -243,11 +250,14 @@
#define QCOM_ID_QRU1000 539
#define QCOM_ID_QDU1000 545
#define QCOM_ID_QDU1010 587
#define QCOM_ID_IPQ5019 569
#define QCOM_ID_QRU1032 588
#define QCOM_ID_QRU1052 589
#define QCOM_ID_QRU1062 590
#define QCOM_ID_IPQ5332 592
#define QCOM_ID_IPQ5322 593
#define QCOM_ID_IPQ5312 594
#define QCOM_ID_IPQ5302 595
/*
* The board type and revision information, used by Qualcomm bootloaders and

View File

@ -11,4 +11,6 @@ int qcom_smem_get_free_space(unsigned host);
phys_addr_t qcom_smem_virt_to_phys(void *p);
int qcom_smem_get_soc_id(u32 *id);
#endif

View File

@ -0,0 +1,70 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __QCOM_SOCINFO_H__
#define __QCOM_SOCINFO_H__
/*
* SMEM item id, used to acquire handles to respective
* SMEM region.
*/
#define SMEM_HW_SW_BUILD_ID 137
#define SMEM_SOCINFO_BUILD_ID_LENGTH 32
#define SMEM_SOCINFO_CHIP_ID_LENGTH 32
/* 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;
/* Version 13 */
__le32 nproduct_id;
char chip_id[SMEM_SOCINFO_CHIP_ID_LENGTH];
/* Version 14 */
__le32 num_clusters;
__le32 ncluster_array_offset;
__le32 num_defective_parts;
__le32 ndefective_parts_array_offset;
/* Version 15 */
__le32 nmodem_supported;
/* Version 16 */
__le32 feature_code;
__le32 pcode;
__le32 npartnamemap_offset;
__le32 nnum_partname_mapping;
/* Version 17 */
__le32 oem_variant;
};
#endif