Qualcomm driver updates for v5.15

This fixes the "shared memory state machine" (SMSM) interrupt logic to
 avoid missing transitions happening while the interrupts are masked.
 
 SM6115 support is added to smd-rpm and rpmpd.
 
 The Qualcomm SCM firmware driver is once again made possible to compile
 and load as a kernel module.
 
 An out-of-bounds error related to the cooling devices of the AOSS driver
 is corrected. The binding is converted to YAML and a generic compatible
 is introduced to reduce the driver churn.
 
 The GENI wrapper gains a helper function used in I2C and SPI for
 switching the serial engine hardware to use the wrapper's DMA-engine.
 
 Lastly it contains a number of cleanups and smaller fixes for rpmhpd,
 socinfo, CPR, mdt_loader and the GENI DT binding.
 -----BEGIN PGP SIGNATURE-----
 
 iQJPBAABCAA5FiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmEa29wbHGJqb3JuLmFu
 ZGVyc3NvbkBsaW5hcm8ub3JnAAoJEAsfOT8Nma3FFnMP/A2Od7JYhdjH7sfc3i3B
 0zws88lT7XTo9KSMpLFrQg1Qzp3ELDMfVhS2CpsekZn1g7s6RGnbQrh2Mac9Yh4z
 +7e4YLhoMxEkdbEVvbVRIX4parFWD/KxUdkyXM8gKZntJzOFl6VY5V8aKi+7IO+/
 CdWHvELDVXMe2LkBd3lKE1AlS2MjkohXpFKgRwkY4r2nVXwqYTdkfJvXdGdhECGr
 ld4ZIvIR6ERLmVpGvTxdU5W0z2xsLTbPYDPSv6mPkWqDYSOyXV3zABV1fSkH28ot
 wIoesHyI3vL4/LNIlHn+tcWj1Ou8hSzxZmxfq7cdKbkfwPLCWE5D8+HEO4kmbFiF
 5Dds+oxvKSFpf/wppK7bUSEd9Q+dKsrFt2mdWy/sYRe1EaEv5sFBgE0rV3+c6ykL
 tptUEFlaB2si7PKSpKje8czHn4Akuc6BwT6xovZZ72K8CNz9D71etSkoNLLXa54d
 bJibw2eNTT1EOACC/FPBO9AS11Icm6wszn/dcaSwaSPGQ6cR3lvAwHqzDFMGHp+x
 L+iojgnZoHykFhQjGuGrI3yTHOpp0MCNxRoN7DlFwm7KLKVHqeqg+xHXtV9sJer8
 iAhY/uepLRxc1oC5Z+Ejx1gABmKycXtzKQ9ecwTclrk66ampWQBlv5+Bxd5w/hux
 ZR96mJPmpk1WKOX3FAgdeaaP
 =88qN
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmEdDA4ACgkQmmx57+YA
 GNmAmw//WfdprWl2SJGfyojhDeeUq6ZeNesMFBabFss7Ar++szhyFSu3bqlyH6WC
 ZgPOZOJakKQq2EGKNm7RuEgeR8sEUs9czetNO8AqVy1szlhqnUKhG0OO+uLqRLQn
 Hvf1fc+uG3xeaFP0/Q/4fuG+GL1fnmXIJWl0nZFUGfWyQ3mxxm5fLq1DM27KAzP1
 eKMqtCh3F0qHMWZTJd084LO2XXyUTVVBbXAQKX/IQmH6+BK3Q2YMToo/919HCnZs
 XfgcdKuB/fOfi1n+PgGNODdTJ/Uy10WkSALZHlzKfr77AUCs9+RWxdkogCmACJBs
 IhNoZ/6D6a6kCIEuaEjHtNsMAVoG0bYpaB9vFLhJgF4wfdCd+DuOXkCy9B7vI4/8
 7/SKArKYrG1sPlhDGFaWZjWEFBCGycDDsHQ4T2ecZ5d3f+Kuimgx7NLYhKRHPI+9
 8QVJwNbIGrNXjwIn6S0AeqDLoXIzMmAbNvuX1lFz0OyEkbgDYPSuUPmKYoKh0VL5
 +aTPYANbKxfF7nIPxfN580yjQGZmJmctyhkqnavEB6HdNySO2/oM5F2uGRVdVKnv
 5HaPLqWZf2PffjAg+bU3O3bBlYRdIpEaKaa1eHFIMTgK7nlcvFESWWtwg+IBKdqY
 JI3Kkg5PP3jxqxybzgFPE298vI1G6/so2A12HBi0dl28XheK+wM=
 =dS58
 -----END PGP SIGNATURE-----

Merge tag 'qcom-drivers-for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers

Qualcomm driver updates for v5.15

This fixes the "shared memory state machine" (SMSM) interrupt logic to
avoid missing transitions happening while the interrupts are masked.

SM6115 support is added to smd-rpm and rpmpd.

The Qualcomm SCM firmware driver is once again made possible to compile
and load as a kernel module.

An out-of-bounds error related to the cooling devices of the AOSS driver
is corrected. The binding is converted to YAML and a generic compatible
is introduced to reduce the driver churn.

The GENI wrapper gains a helper function used in I2C and SPI for
switching the serial engine hardware to use the wrapper's DMA-engine.

Lastly it contains a number of cleanups and smaller fixes for rpmhpd,
socinfo, CPR, mdt_loader and the GENI DT binding.

* tag 'qcom-drivers-for-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux:
  soc: qcom: smsm: Fix missed interrupts if state changes while masked
  soc: qcom: smsm: Implement support for get_irqchip_state
  soc: qcom: mdt_loader: be more informative on errors
  dt-bindings: qcom: geni-se: document iommus
  soc: qcom: smd-rpm: Add SM6115 compatible
  soc: qcom: geni: Add support for gpi dma
  soc: qcom: geni: move GENI_IF_DISABLE_RO to common header
  PM: AVS: qcom-cpr: Use nvmem_cell_read_variable_le_u32()
  drivers: soc: qcom: rpmpd: Add SM6115 RPM Power Domains
  dt-bindings: power: rpmpd: Add SM6115 to rpmpd binding
  dt-bindings: soc: qcom: smd-rpm: Add SM6115 compatible
  soc: qcom: aoss: Fix the out of bound usage of cooling_devs
  firmware: qcom_scm: Allow qcom_scm driver to be loadable as a permenent module
  soc: qcom: socinfo: Don't print anything if nothing found
  soc: qcom: rpmhpd: Use corner in power_off
  soc: qcom: aoss: Add generic compatible
  dt-bindings: soc: qcom: aoss: Convert to YAML
  dt-bindings: soc: qcom: aoss: Add SC8180X and generic compatible
  firmware: qcom_scm: remove a duplicative condition
  firmware: qcom_scm: Mark string array const

Link: https://lore.kernel.org/r/20210816214840.581244-1-bjorn.andersson@linaro.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2021-08-18 15:33:01 +02:00
commit 5c785014b6
21 changed files with 269 additions and 148 deletions

View file

@ -30,6 +30,7 @@ properties:
- qcom,sc8180x-rpmhpd
- qcom,sdm845-rpmhpd
- qcom,sdx55-rpmhpd
- qcom,sm6115-rpmpd
- qcom,sm8150-rpmhpd
- qcom,sm8250-rpmhpd
- qcom,sm8350-rpmhpd

View file

@ -1,87 +0,0 @@
Qualcomm Always-On Subsystem side channel binding
This binding describes the hardware component responsible for side channel
requests to the always-on subsystem (AOSS), used for certain power management
requests that is not handled by the standard RPMh interface. Each client in the
SoC has it's own block of message RAM and IRQ for communication with the AOSS.
The protocol used to communicate in the message RAM is known as Qualcomm
Messaging Protocol (QMP)
The AOSS side channel exposes control over a set of resources, used to control
a set of debug related clocks and to affect the low power state of resources
related to the secondary subsystems. These resources are exposed as a set of
power-domains.
- compatible:
Usage: required
Value type: <string>
Definition: must be one of:
"qcom,sc7180-aoss-qmp"
"qcom,sc7280-aoss-qmp"
"qcom,sdm845-aoss-qmp"
"qcom,sm8150-aoss-qmp"
"qcom,sm8250-aoss-qmp"
"qcom,sm8350-aoss-qmp"
- reg:
Usage: required
Value type: <prop-encoded-array>
Definition: the base address and size of the message RAM for this
client's communication with the AOSS
- interrupts:
Usage: required
Value type: <prop-encoded-array>
Definition: should specify the AOSS message IRQ for this client
- mboxes:
Usage: required
Value type: <prop-encoded-array>
Definition: reference to the mailbox representing the outgoing doorbell
in APCS for this client, as described in mailbox/mailbox.txt
- #clock-cells:
Usage: optional
Value type: <u32>
Definition: must be 0
The single clock represents the QDSS clock.
- #power-domain-cells:
Usage: optional
Value type: <u32>
Definition: must be 1
The provided power-domains are:
CDSP state (0), LPASS state (1), modem state (2), SLPI
state (3), SPSS state (4) and Venus state (5).
= SUBNODES
The AOSS side channel also provides the controls for three cooling devices,
these are expressed as subnodes of the QMP node. The name of the node is used
to identify the resource and must therefor be "cx", "mx" or "ebi".
- #cooling-cells:
Usage: optional
Value type: <u32>
Definition: must be 2
= EXAMPLE
The following example represents the AOSS side-channel message RAM and the
mechanism exposing the power-domains, as found in SDM845.
aoss_qmp: qmp@c300000 {
compatible = "qcom,sdm845-aoss-qmp";
reg = <0x0c300000 0x100000>;
interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>;
mboxes = <&apss_shared 0>;
#power-domain-cells = <1>;
cx_cdev: cx {
#cooling-cells = <2>;
};
mx_cdev: mx {
#cooling-cells = <2>;
};
};

View file

@ -0,0 +1,114 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/soc/qcom/qcom,aoss-qmp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Always-On Subsystem side channel binding
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description:
This binding describes the hardware component responsible for side channel
requests to the always-on subsystem (AOSS), used for certain power management
requests that is not handled by the standard RPMh interface. Each client in the
SoC has it's own block of message RAM and IRQ for communication with the AOSS.
The protocol used to communicate in the message RAM is known as Qualcomm
Messaging Protocol (QMP)
The AOSS side channel exposes control over a set of resources, used to control
a set of debug related clocks and to affect the low power state of resources
related to the secondary subsystems. These resources are exposed as a set of
power-domains.
properties:
compatible:
items:
- enum:
- qcom,sc7180-aoss-qmp
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp
- qcom,sdm845-aoss-qmp
- qcom,sm8150-aoss-qmp
- qcom,sm8250-aoss-qmp
- qcom,sm8350-aoss-qmp
- const: qcom,aoss-qmp
reg:
maxItems: 1
description:
The base address and size of the message RAM for this client's
communication with the AOSS
interrupts:
maxItems: 1
description:
Should specify the AOSS message IRQ for this client
mboxes:
maxItems: 1
description:
Reference to the mailbox representing the outgoing doorbell in APCS for
this client, as described in mailbox/mailbox.txt
"#clock-cells":
const: 0
description:
The single clock represents the QDSS clock.
"#power-domain-cells":
const: 1
description: |
The provided power-domains are:
CDSP state (0), LPASS state (1), modem state (2), SLPI
state (3), SPSS state (4) and Venus state (5).
required:
- compatible
- reg
- interrupts
- mboxes
- "#clock-cells"
additionalProperties: false
patternProperties:
"^(cx|mx|ebi)$":
type: object
description:
The AOSS side channel also provides the controls for three cooling devices,
these are expressed as subnodes of the QMP node. The name of the node is
used to identify the resource and must therefor be "cx", "mx" or "ebi".
properties:
"#cooling-cells":
const: 2
required:
- "#cooling-cells"
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
aoss_qmp: qmp@c300000 {
compatible = "qcom,sdm845-aoss-qmp", "qcom,aoss-qmp";
reg = <0x0c300000 0x100000>;
interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>;
mboxes = <&apss_shared 0>;
#clock-cells = <0>;
#power-domain-cells = <1>;
cx_cdev: cx {
#cooling-cells = <2>;
};
mx_cdev: mx {
#cooling-cells = <2>;
};
};
...

View file

@ -51,6 +51,9 @@ properties:
interconnect-names:
const: qup-core
iommus:
maxItems: 1
required:
- compatible
- reg

View file

@ -39,6 +39,7 @@ properties:
- qcom,rpm-msm8996
- qcom,rpm-msm8998
- qcom,rpm-sdm660
- qcom,rpm-sm6115
- qcom,rpm-sm6125
- qcom,rpm-qcs404

View file

@ -203,7 +203,7 @@ config INTEL_STRATIX10_RSU
Say Y here if you want Intel RSU support.
config QCOM_SCM
bool
tristate "Qcom SCM driver"
depends on ARM || ARM64
depends on HAVE_ARM_SMCCC
select RESET_CONTROLLER

View file

@ -17,7 +17,8 @@ obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
obj-$(CONFIG_RASPBERRYPI_FIRMWARE) += raspberrypi.o
obj-$(CONFIG_FW_CFG_SYSFS) += qemu_fw_cfg.o
obj-$(CONFIG_QCOM_SCM) += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
obj-$(CONFIG_QCOM_SCM) += qcom-scm.o
qcom-scm-objs += qcom_scm.o qcom_scm-smc.o qcom_scm-legacy.o
obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o
obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o
obj-$(CONFIG_TURRIS_MOX_RWTM) += turris-mox-rwtm.o

View file

@ -71,7 +71,7 @@ static struct qcom_scm_wb_entry qcom_scm_wb[] = {
{ .flag = QCOM_SCM_FLAG_WARMBOOT_CPU3 },
};
static const char *qcom_scm_convention_names[] = {
static const char * const qcom_scm_convention_names[] = {
[SMC_CONVENTION_UNKNOWN] = "unknown",
[SMC_CONVENTION_ARM_32] = "smc arm 32",
[SMC_CONVENTION_ARM_64] = "smc arm 64",
@ -331,7 +331,7 @@ int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
.owner = ARM_SMCCC_OWNER_SIP,
};
if (!cpus || (cpus && cpumask_empty(cpus)))
if (!cpus || cpumask_empty(cpus))
return -EINVAL;
for_each_cpu(cpu, cpus) {
@ -1299,6 +1299,7 @@ static const struct of_device_id qcom_scm_dt_match[] = {
{ .compatible = "qcom,scm" },
{}
};
MODULE_DEVICE_TABLE(of, qcom_scm_dt_match);
static struct platform_driver qcom_scm_driver = {
.driver = {
@ -1315,3 +1316,6 @@ static int __init qcom_scm_init(void)
return platform_driver_register(&qcom_scm_driver);
}
subsys_initcall(qcom_scm_init);
MODULE_DESCRIPTION("Qualcomm Technologies, Inc. SCM driver");
MODULE_LICENSE("GPL v2");

View file

@ -253,6 +253,7 @@ config SPAPR_TCE_IOMMU
config ARM_SMMU
tristate "ARM Ltd. System MMU (SMMU) Support"
depends on ARM64 || ARM || (COMPILE_TEST && !GENERIC_ATOMIC64)
depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select ARM_DMA_USE_IOMMU if ARM
@ -382,6 +383,7 @@ config QCOM_IOMMU
# Note: iommu drivers cannot (yet?) be built as modules
bool "Qualcomm IOMMU Support"
depends on ARCH_QCOM || (COMPILE_TEST && !GENERIC_ATOMIC64)
depends on QCOM_SCM=y
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select ARM_DMA_USE_IOMMU

View file

@ -44,6 +44,7 @@ config ATH10K_SNOC
tristate "Qualcomm ath10k SNOC support"
depends on ATH10K
depends on ARCH_QCOM || COMPILE_TEST
depends on QCOM_SCM || !QCOM_SCM #if QCOM_SCM=m this can't be =y
select QCOM_QMI_HELPERS
help
This module adds support for integrated WCN3990 chip connected

View file

@ -801,38 +801,6 @@ static int cpr_set_performance_state(struct generic_pm_domain *domain,
return ret;
}
static int cpr_read_efuse(struct device *dev, const char *cname, u32 *data)
{
struct nvmem_cell *cell;
ssize_t len;
char *ret;
int i;
*data = 0;
cell = nvmem_cell_get(dev, cname);
if (IS_ERR(cell)) {
if (PTR_ERR(cell) != -EPROBE_DEFER)
dev_err(dev, "undefined cell %s\n", cname);
return PTR_ERR(cell);
}
ret = nvmem_cell_read(cell, &len);
nvmem_cell_put(cell);
if (IS_ERR(ret)) {
dev_err(dev, "can't read cell %s\n", cname);
return PTR_ERR(ret);
}
for (i = 0; i < len; i++)
*data |= ret[i] << (8 * i);
kfree(ret);
dev_dbg(dev, "efuse read(%s) = %x, bytes %zd\n", cname, *data, len);
return 0;
}
static int
cpr_populate_ring_osc_idx(struct cpr_drv *drv)
{
@ -843,8 +811,7 @@ cpr_populate_ring_osc_idx(struct cpr_drv *drv)
int ret;
for (; fuse < end; fuse++, fuses++) {
ret = cpr_read_efuse(drv->dev, fuses->ring_osc,
&data);
ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->ring_osc, &data);
if (ret)
return ret;
fuse->ring_osc_idx = data;
@ -863,7 +830,7 @@ static int cpr_read_fuse_uV(const struct cpr_desc *desc,
u32 bits = 0;
int ret;
ret = cpr_read_efuse(drv->dev, init_v_efuse, &bits);
ret = nvmem_cell_read_variable_le_u32(drv->dev, init_v_efuse, &bits);
if (ret)
return ret;
@ -932,7 +899,7 @@ static int cpr_fuse_corner_init(struct cpr_drv *drv)
}
/* Populate target quotient by scaling */
ret = cpr_read_efuse(drv->dev, fuses->quotient, &fuse->quot);
ret = nvmem_cell_read_variable_le_u32(drv->dev, fuses->quotient, &fuse->quot);
if (ret)
return ret;
@ -1001,7 +968,7 @@ static int cpr_calculate_scaling(const char *quot_offset,
prev_fuse = fuse - 1;
if (quot_offset) {
ret = cpr_read_efuse(drv->dev, quot_offset, &quot_diff);
ret = nvmem_cell_read_variable_le_u32(drv->dev, quot_offset, &quot_diff);
if (ret)
return ret;
@ -1701,7 +1668,7 @@ static int cpr_probe(struct platform_device *pdev)
* initialized after attaching to the power domain,
* since it depends on the CPU's OPP table.
*/
ret = cpr_read_efuse(dev, "cpr_fuse_revision", &cpr_rev);
ret = nvmem_cell_read_variable_le_u32(dev, "cpr_fuse_revision", &cpr_rev);
if (ret)
return ret;

View file

@ -166,6 +166,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
metadata = qcom_mdt_read_metadata(fw, &metadata_len);
if (IS_ERR(metadata)) {
ret = PTR_ERR(metadata);
dev_err(dev, "error %d reading firmware %s metadata\n",
ret, fw_name);
goto out;
}
@ -173,7 +175,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
kfree(metadata);
if (ret) {
dev_err(dev, "invalid firmware metadata\n");
/* Invalid firmware metadata */
dev_err(dev, "error %d initializing firmware %s\n",
ret, fw_name);
goto out;
}
}
@ -199,7 +203,9 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret = qcom_scm_pas_mem_setup(pas_id, mem_phys,
max_addr - min_addr);
if (ret) {
dev_err(dev, "unable to setup relocation\n");
/* Unable to set up relocation */
dev_err(dev, "error %d setting up firmware %s\n",
ret, fw_name);
goto out;
}
}
@ -243,9 +249,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (phdr->p_filesz && phdr->p_offset < fw->size) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
dev_err(dev,
"failed to load segment %d from truncated file %s\n",
i, firmware);
dev_err(dev, "file %s segment %d would be truncated\n",
fw_name, i);
ret = -EINVAL;
break;
}
@ -257,7 +262,8 @@ static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
ptr, phdr->p_filesz);
if (ret) {
dev_err(dev, "failed to load %s\n", fw_name);
dev_err(dev, "error %d loading %s\n",
ret, fw_name);
break;
}

View file

@ -104,7 +104,6 @@ static const char * const icc_path_names[] = {"qup-core", "qup-config",
#define GENI_OUTPUT_CTRL 0x24
#define GENI_CGC_CTRL 0x28
#define GENI_CLK_CTRL_RO 0x60
#define GENI_IF_DISABLE_RO 0x64
#define GENI_FW_S_REVISION_RO 0x6c
#define SE_GENI_BYTE_GRAN 0x254
#define SE_GENI_TX_PACKING_CFG0 0x260
@ -322,6 +321,30 @@ static void geni_se_select_dma_mode(struct geni_se *se)
writel_relaxed(val, se->base + SE_GENI_DMA_MODE_EN);
}
static void geni_se_select_gpi_mode(struct geni_se *se)
{
u32 val;
geni_se_irq_clear(se);
writel(0, se->base + SE_IRQ_EN);
val = readl(se->base + SE_GENI_S_IRQ_EN);
val &= ~S_CMD_DONE_EN;
writel(val, se->base + SE_GENI_S_IRQ_EN);
val = readl(se->base + SE_GENI_M_IRQ_EN);
val &= ~(M_CMD_DONE_EN | M_TX_FIFO_WATERMARK_EN |
M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN);
writel(val, se->base + SE_GENI_M_IRQ_EN);
writel(GENI_DMA_MODE_EN, se->base + SE_GENI_DMA_MODE_EN);
val = readl(se->base + SE_GSI_EVENT_EN);
val |= (DMA_RX_EVENT_EN | DMA_TX_EVENT_EN | GENI_M_EVENT_EN | GENI_S_EVENT_EN);
writel(val, se->base + SE_GSI_EVENT_EN);
}
/**
* geni_se_select_mode() - Select the serial engine transfer mode
* @se: Pointer to the concerned serial engine.
@ -329,7 +352,7 @@ static void geni_se_select_dma_mode(struct geni_se *se)
*/
void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
{
WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA);
WARN_ON(mode != GENI_SE_FIFO && mode != GENI_SE_DMA && mode != GENI_GPI_DMA);
switch (mode) {
case GENI_SE_FIFO:
@ -338,6 +361,9 @@ void geni_se_select_mode(struct geni_se *se, enum geni_se_xfer_mode mode)
case GENI_SE_DMA:
geni_se_select_dma_mode(se);
break;
case GENI_GPI_DMA:
geni_se_select_gpi_mode(se);
break;
case GENI_SE_INVALID:
default:
break;

View file

@ -476,12 +476,12 @@ static int qmp_cooling_device_add(struct qmp *qmp,
static int qmp_cooling_devices_register(struct qmp *qmp)
{
struct device_node *np, *child;
int count = QMP_NUM_COOLING_RESOURCES;
int count = 0;
int ret;
np = qmp->dev->of_node;
qmp->cooling_devs = devm_kcalloc(qmp->dev, count,
qmp->cooling_devs = devm_kcalloc(qmp->dev, QMP_NUM_COOLING_RESOURCES,
sizeof(*qmp->cooling_devs),
GFP_KERNEL);
@ -497,12 +497,16 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
goto unroll;
}
if (!count)
devm_kfree(qmp->dev, qmp->cooling_devs);
return 0;
unroll:
while (--count >= 0)
thermal_cooling_device_unregister
(qmp->cooling_devs[count].cdev);
devm_kfree(qmp->dev, qmp->cooling_devs);
return ret;
}
@ -602,6 +606,7 @@ static const struct of_device_id qmp_dt_match[] = {
{ .compatible = "qcom,sm8150-aoss-qmp", },
{ .compatible = "qcom,sm8250-aoss-qmp", },
{ .compatible = "qcom,sm8350-aoss-qmp", },
{ .compatible = "qcom,aoss-qmp", },
{}
};
MODULE_DEVICE_TABLE(of, qmp_dt_match);

View file

@ -403,12 +403,11 @@ static int rpmhpd_power_on(struct generic_pm_domain *domain)
static int rpmhpd_power_off(struct generic_pm_domain *domain)
{
struct rpmhpd *pd = domain_to_rpmhpd(domain);
int ret = 0;
int ret;
mutex_lock(&rpmhpd_lock);
ret = rpmhpd_aggregate_corner(pd, pd->level[0]);
ret = rpmhpd_aggregate_corner(pd, 0);
if (!ret)
pd->enabled = false;

View file

@ -346,6 +346,33 @@ static const struct rpmpd_desc sdm660_desc = {
.max_state = RPM_SMD_LEVEL_TURBO,
};
/* sm4250/6115 RPM Power domains */
DEFINE_RPMPD_PAIR(sm6115, vddcx, vddcx_ao, RWCX, LEVEL, 0);
DEFINE_RPMPD_VFL(sm6115, vddcx_vfl, RWCX, 0);
DEFINE_RPMPD_PAIR(sm6115, vddmx, vddmx_ao, RWMX, LEVEL, 0);
DEFINE_RPMPD_VFL(sm6115, vddmx_vfl, RWMX, 0);
DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_cx, RWLC, 0);
DEFINE_RPMPD_LEVEL(sm6115, vdd_lpi_mx, RWLM, 0);
static struct rpmpd *sm6115_rpmpds[] = {
[SM6115_VDDCX] = &sm6115_vddcx,
[SM6115_VDDCX_AO] = &sm6115_vddcx_ao,
[SM6115_VDDCX_VFL] = &sm6115_vddcx_vfl,
[SM6115_VDDMX] = &sm6115_vddmx,
[SM6115_VDDMX_AO] = &sm6115_vddmx_ao,
[SM6115_VDDMX_VFL] = &sm6115_vddmx_vfl,
[SM6115_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
[SM6115_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
};
static const struct rpmpd_desc sm6115_desc = {
.rpmpds = sm6115_rpmpds,
.num_pds = ARRAY_SIZE(sm6115_rpmpds),
.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
};
static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc },
{ .compatible = "qcom,msm8916-rpmpd", .data = &msm8916_desc },
@ -356,6 +383,7 @@ static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc },
{ .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc },
{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
{ }
};
MODULE_DEVICE_TABLE(of, rpmpd_match_table);

View file

@ -242,6 +242,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-msm8996" },
{ .compatible = "qcom,rpm-msm8998" },
{ .compatible = "qcom,rpm-sdm660" },
{ .compatible = "qcom,rpm-sm6115" },
{ .compatible = "qcom,rpm-sm6125" },
{ .compatible = "qcom,rpm-qcs404" },
{}

View file

@ -109,7 +109,7 @@ struct smsm_entry {
DECLARE_BITMAP(irq_enabled, 32);
DECLARE_BITMAP(irq_rising, 32);
DECLARE_BITMAP(irq_falling, 32);
u32 last_value;
unsigned long last_value;
u32 *remote_state;
u32 *subscription;
@ -204,8 +204,7 @@ static irqreturn_t smsm_intr(int irq, void *data)
u32 val;
val = readl(entry->remote_state);
changed = val ^ entry->last_value;
entry->last_value = val;
changed = val ^ xchg(&entry->last_value, val);
for_each_set_bit(i, entry->irq_enabled, 32) {
if (!(changed & BIT(i)))
@ -264,6 +263,12 @@ static void smsm_unmask_irq(struct irq_data *irqd)
struct qcom_smsm *smsm = entry->smsm;
u32 val;
/* Make sure our last cached state is up-to-date */
if (readl(entry->remote_state) & BIT(irq))
set_bit(irq, &entry->last_value);
else
clear_bit(irq, &entry->last_value);
set_bit(irq, entry->irq_enabled);
if (entry->subscription) {
@ -299,11 +304,28 @@ static int smsm_set_irq_type(struct irq_data *irqd, unsigned int type)
return 0;
}
static int smsm_get_irqchip_state(struct irq_data *irqd,
enum irqchip_irq_state which, bool *state)
{
struct smsm_entry *entry = irq_data_get_irq_chip_data(irqd);
irq_hw_number_t irq = irqd_to_hwirq(irqd);
u32 val;
if (which != IRQCHIP_STATE_LINE_LEVEL)
return -EINVAL;
val = readl(entry->remote_state);
*state = !!(val & BIT(irq));
return 0;
}
static struct irq_chip smsm_irq_chip = {
.name = "smsm",
.irq_mask = smsm_mask_irq,
.irq_unmask = smsm_unmask_irq,
.irq_set_type = smsm_set_irq_type,
.irq_get_irqchip_state = smsm_get_irqchip_state,
};
/**

View file

@ -417,8 +417,8 @@ QCOM_OPEN(chip_id, qcom_show_chip_id);
static int show_image_##type(struct seq_file *seq, void *p) \
{ \
struct smem_image_version *image_version = seq->private; \
seq_puts(seq, image_version->type); \
seq_putc(seq, '\n'); \
if (image_version->type[0] != '\0') \
seq_printf(seq, "%s\n", image_version->type); \
return 0; \
} \
static int open_image_##type(struct inode *inode, struct file *file) \

View file

@ -192,6 +192,16 @@
#define SDM660_SSCMX 8
#define SDM660_SSCMX_VFL 9
/* SM6115 Power Domains */
#define SM6115_VDDCX 0
#define SM6115_VDDCX_AO 1
#define SM6115_VDDCX_VFL 2
#define SM6115_VDDMX 3
#define SM6115_VDDMX_AO 4
#define SM6115_VDDMX_VFL 5
#define SM6115_VDD_LPI_CX 6
#define SM6115_VDD_LPI_MX 7
/* RPM SMD Power Domain performance levels */
#define RPM_SMD_LEVEL_RETENTION 16
#define RPM_SMD_LEVEL_RETENTION_PLUS 32

View file

@ -8,11 +8,24 @@
#include <linux/interconnect.h>
/* Transfer mode supported by GENI Serial Engines */
/**
* enum geni_se_xfer_mode: Transfer modes supported by Serial Engines
*
* @GENI_SE_INVALID: Invalid mode
* @GENI_SE_FIFO: FIFO mode. Data is transferred with SE FIFO
* by programmed IO method
* @GENI_SE_DMA: Serial Engine DMA mode. Data is transferred
* with SE by DMAengine internal to SE
* @GENI_GPI_DMA: GPI DMA mode. Data is transferred using a DMAengine
* configured by a firmware residing on a GSI engine. This DMA name is
* interchangeably used as GSI or GPI which seem to imply the same DMAengine
*/
enum geni_se_xfer_mode {
GENI_SE_INVALID,
GENI_SE_FIFO,
GENI_SE_DMA,
GENI_GPI_DMA,
};
/* Protocols supported by GENI Serial Engines */
@ -63,6 +76,7 @@ struct geni_se {
#define SE_GENI_STATUS 0x40
#define GENI_SER_M_CLK_CFG 0x48
#define GENI_SER_S_CLK_CFG 0x4c
#define GENI_IF_DISABLE_RO 0x64
#define GENI_FW_REVISION_RO 0x68
#define SE_GENI_CLK_SEL 0x7c
#define SE_GENI_DMA_MODE_EN 0x258
@ -105,6 +119,9 @@ struct geni_se {
#define CLK_DIV_MSK GENMASK(15, 4)
#define CLK_DIV_SHFT 4
/* GENI_IF_DISABLE_RO fields */
#define FIFO_IF_DISABLE (BIT(0))
/* GENI_FW_REVISION_RO fields */
#define FW_REV_PROTOCOL_MSK GENMASK(15, 8)
#define FW_REV_PROTOCOL_SHFT 8