Qualcomm driver updates for 6.1

The icc-bwmon driver is expected to support measuring LLCC/DDR bandwidth
 on SDM845 and SC7280.
 
 The LLCC driver is extended to provide per-platform register mappings to
 the LLCC EDAC driver. The QMI encoder/decoder is updated to allow the
 passed qmi_elem_info to be const.
 
 Support for SDM845 is added to the sleep stats driver. Power-domains for
 the SM6375 platform is added to RPMPD and the platform is added to
 socinfo, together with the PM6125 pmic id.
 
 A couple of of_node reference issues are corrected in the smem state and
 smsm drivers.
 
 The Qualcomm SCM driver binding is converted to YAML.
 -----BEGIN PGP SIGNATURE-----
 
 iQJJBAABCAAzFiEEBd4DzF816k8JZtUlCx85Pw2ZrcUFAmMrMtQVHGFuZGVyc3Nv
 bkBrZXJuZWwub3JnAAoJEAsfOT8Nma3Foy8P/3xNqiQAVdWD/49rycmoNg02Jg6A
 L9WM0GI1TMKCJV+tr2QFFknFOzTxr4VhIefddUWWJYGnzN89sHqYbWjBbnPaHVv/
 Im7opHZ1Aq5hPct5TvlXrMjNDhe3+2y44qv4+H9q8Kk7nOVUQwOfE3J7VE71B1tO
 gLHEdlafSH+M62PJsiDQRIgtU2jfFBBpOC+J4OazvRsYQboI29U5Aro08Yqy/KFq
 opEMJlnetzPl1zI+7Tu56V8gVWnBIedQJJCT/EZEWMJ8Lf8XMbuTaTrW+ioSnjrT
 SyLgAzvLCI8yMOaLSssdpk6pgtsMleqRI/SHlvUX2+sUlxK3Gycw9rxsU6RJ80gk
 SRjYXEwr78w4QGcC/eY8Lg+d0xi/A1MOMGLYoQGyKzHtyi+q1x3yQQ5HW6YS0qlO
 J6a9zSL2PNfLyXv7DE1PblKUZtifV/8U+gYviwe09Rj7mkZWzlOC946uUp4B9VEE
 R96qoLZtyvgAzBCnpWIJ0IwYSRdqVNYpDKKb4CGQ9qAdyHZIg+DL9i6vozwWsyZk
 gRTXo4K9MuqHya+vZYOH4zyi8eIHgqdSNSbo/4893E3GcAtPBw1YRdCPWNPITdQg
 bcTfg/7bFymeHN3arbkXjclXp1O12JA+umsPnRnWtmmoCPNqh8wki4v32dqcpyQq
 FvkQpszZbeHQGxq4
 =R/5I
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmMt02wACgkQmmx57+YA
 GNlEyw/+Je0NXWJdKYHw9+nkc5GJCrB7Sytz9xmavB/1JMTDyjMcRgbmXg0gl1ZF
 6gYACVcv1GgIFFrDrjEHm81qVunjr+z3oyqY/Tr4XDk2AvFJicX/kltSOxWozHrV
 TYGd3HtneGMA6jhT7T76b849N4p0S9gJu62+tQiD2wa31oFAnfhrf790QJZahHZf
 /VPGiNiOhINMJJk+rUal8R4A8CWXdx9GTTulhcSD3g9HPTWJuq+SJ6SSCuNmOLPO
 4KZeWytBmihSWIjWsyuKUwSmK1ceNH/Vt6QhenPUZynZ4ojuJOUeOTnkf+mR6M2A
 ysetlsi8GDiQSWW/hb/+b733YFOTVVFbigEjt6B40HKLAXlgiAqwCVzWFQ61Eg48
 UNnx26RUlT3PGw0oF1pSOvl8a/0DDKhzteyQSJQ/gR59SKLjhwEB27Ml1C2B+VVM
 FHn0WnhnAvC6qPBrRh6HUVtoqblRsaT6UJ+qwr6TDhmiDMTmQP49dMbA9Me+lphb
 ACbhqk+yUoaYhq6oK2pneqtgP0A4QuFSZAzGE6tXryILYeme+LOpL2ff2NNAsY5C
 6jX+6oyAZVSmJKs0itQyTyQqmJ/5bFp8ob5dpwNeFMLgRvohpDh/EChjkTV7N0EU
 NK12FkJIvDptBFMOClVx5PurCLPwG4cI2/qIZ8xHuEdzrpELYgI=
 =GSE8
 -----END PGP SIGNATURE-----

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

Qualcomm driver updates for 6.1

The icc-bwmon driver is expected to support measuring LLCC/DDR bandwidth
on SDM845 and SC7280.

The LLCC driver is extended to provide per-platform register mappings to
the LLCC EDAC driver. The QMI encoder/decoder is updated to allow the
passed qmi_elem_info to be const.

Support for SDM845 is added to the sleep stats driver. Power-domains for
the SM6375 platform is added to RPMPD and the platform is added to
socinfo, together with the PM6125 pmic id.

A couple of of_node reference issues are corrected in the smem state and
smsm drivers.

The Qualcomm SCM driver binding is converted to YAML.

* tag 'qcom-drivers-for-6.1' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (29 commits)
  soc: qcom: rpmpd: Add SM6375 support
  dt-bindings: power: rpmpd: Add SM6375 power domains
  firmware: qcom: scm: remove unused __qcom_scm_init declaration
  dt-bindings: power: qcom,rpmpd: drop non-working codeaurora.org emails
  soc: qcom: icc-bwmon: force clear counter/irq registers
  soc: qcom: icc-bwmon: add support for sc7280 LLCC BWMON
  dt-bindings: interconnect: qcom,msm8998-bwmon: Add support for sc7280 BWMONs
  soc: qcom: llcc: Pass LLCC version based register offsets to EDAC driver
  soc: qcom: llcc: Rename reg_offset structs to reflect LLCC version
  soc: qcom: qmi: use const for struct qmi_elem_info
  soc: qcom: icc-bwmon: remove redundant ret variable
  dt-bindings: soc: qcom: stats: Document SDM845 compatible
  soc: qcom: stats: Add SDM845 stats config and compatible
  dt-bindings: firmware: document Qualcomm SM6115 SCM
  soc: qcom: Make QCOM_RPMPD depend on OF
  dt-bindings: firmware: convert Qualcomm SCM binding to the yaml
  soc: qcom: socinfo: Add PM6125 ID
  soc: qcom: socinfo: Add an ID for SM6375
  soc: qcom: smem_state: Add refcounting for the 'state->of_node'
  soc: qcom: smsm: Fix refcount leak bugs in qcom_smsm_probe()
  ...

Link: https://lore.kernel.org/r/20220921155753.1316308-1-andersson@kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2022-09-23 17:40:27 +02:00
commit 37d49c249c
20 changed files with 751 additions and 226 deletions

View File

@ -1,61 +0,0 @@
QCOM Secure Channel Manager (SCM)
Qualcomm processors include an interface to communicate to the secure firmware.
This interface allows for clients to request different types of actions. These
can include CPU power up/down, HDCP requests, loading of firmware, and other
assorted actions.
Required properties:
- compatible: must contain one of the following:
* "qcom,scm-apq8064"
* "qcom,scm-apq8084"
* "qcom,scm-ipq4019"
* "qcom,scm-ipq806x"
* "qcom,scm-ipq8074"
* "qcom,scm-mdm9607"
* "qcom,scm-msm8226"
* "qcom,scm-msm8660"
* "qcom,scm-msm8916"
* "qcom,scm-msm8953"
* "qcom,scm-msm8960"
* "qcom,scm-msm8974"
* "qcom,scm-msm8976"
* "qcom,scm-msm8994"
* "qcom,scm-msm8996"
* "qcom,scm-msm8998"
* "qcom,scm-qcs404"
* "qcom,scm-sc7180"
* "qcom,scm-sc7280"
* "qcom,scm-sm6125"
* "qcom,scm-sdm845"
* "qcom,scm-sdx55"
* "qcom,scm-sdx65"
* "qcom,scm-sm6350"
* "qcom,scm-sm8150"
* "qcom,scm-sm8250"
* "qcom,scm-sm8350"
* "qcom,scm-sm8450"
and:
* "qcom,scm"
- clocks: Specifies clocks needed by the SCM interface, if any:
* core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and
"qcom,scm-msm8960"
* core, iface and bus clocks required for "qcom,scm-apq8084",
"qcom,scm-msm8916", "qcom,scm-msm8953", "qcom,scm-msm8974" and "qcom,scm-msm8976"
- clock-names: Must contain "core" for the core clock, "iface" for the interface
clock and "bus" for the bus clock per the requirements of the compatible.
- qcom,dload-mode: phandle to the TCSR hardware block and offset of the
download mode control register (optional)
- interconnects: Specifies the bandwidth requirements of the SCM interface (optional)
Example for MSM8916:
firmware {
scm {
compatible = "qcom,msm8916", "qcom,scm";
clocks = <&gcc GCC_CRYPTO_CLK> ,
<&gcc GCC_CRYPTO_AXI_CLK>,
<&gcc GCC_CRYPTO_AHB_CLK>;
clock-names = "core", "bus", "iface";
};
};

View File

@ -0,0 +1,148 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/firmware/qcom,scm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: QCOM Secure Channel Manager (SCM)
description: |
Qualcomm processors include an interface to communicate to the secure firmware.
This interface allows for clients to request different types of actions.
These can include CPU power up/down, HDCP requests, loading of firmware,
and other assorted actions.
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
- Robert Marko <robimarko@gmail.com>
- Guru Das Srinagesh <quic_gurus@quicinc.com>
properties:
compatible:
items:
- enum:
- qcom,scm-apq8064
- qcom,scm-apq8084
- qcom,scm-ipq4019
- qcom,scm-ipq6018
- qcom,scm-ipq806x
- qcom,scm-ipq8074
- qcom,scm-mdm9607
- qcom,scm-msm8226
- qcom,scm-msm8660
- qcom,scm-msm8916
- qcom,scm-msm8953
- qcom,scm-msm8960
- qcom,scm-msm8974
- qcom,scm-msm8976
- qcom,scm-msm8994
- qcom,scm-msm8996
- qcom,scm-msm8998
- qcom,scm-sc7180
- qcom,scm-sc7280
- qcom,scm-sc8280xp
- qcom,scm-sdm845
- qcom,scm-sdx55
- qcom,scm-sdx65
- qcom,scm-sm6115
- qcom,scm-sm6125
- qcom,scm-sm6350
- qcom,scm-sm8150
- qcom,scm-sm8250
- qcom,scm-sm8350
- qcom,scm-sm8450
- qcom,scm-qcs404
- const: qcom,scm
clocks:
minItems: 1
maxItems: 3
clock-names:
minItems: 1
maxItems: 3
interconnects:
maxItems: 1
interconnect-names:
maxItems: 1
'#reset-cells':
const: 1
qcom,dload-mode:
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
- items:
- description: phandle to TCSR hardware block
- description: offset of the download mode control register
description: TCSR hardware block
allOf:
- if:
properties:
compatible:
contains:
enum:
- qcom,scm-apq8064
- qcom,scm-msm8660
- qcom,scm-msm8960
then:
properties:
clock-names:
items:
- const: core
clocks:
maxItems: 1
required:
- clocks
- clock-names
- if:
properties:
compatible:
contains:
enum:
- qcom,scm-apq8084
- qcom,scm-mdm9607
- qcom,scm-msm8916
- qcom,scm-msm8953
- qcom,scm-msm8974
- qcom,scm-msm8976
then:
properties:
clock-names:
items:
- const: core
- const: bus
- const: iface
clocks:
minItems: 3
maxItems: 3
required:
- clocks
- clock-names
required:
- compatible
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,gcc-msm8916.h>
firmware {
scm {
compatible = "qcom,scm-msm8916", "qcom,scm";
clocks = <&gcc GCC_CRYPTO_CLK>,
<&gcc GCC_CRYPTO_AXI_CLK>,
<&gcc GCC_CRYPTO_AHB_CLK>;
clock-names = "core", "bus", "iface";
};
};

View File

@ -24,9 +24,12 @@ properties:
oneOf:
- items:
- enum:
- qcom,sc7280-bwmon
- qcom,sdm845-bwmon
- const: qcom,msm8998-bwmon
- const: qcom,msm8998-bwmon # BWMON v4
- const: qcom,sc7280-llcc-bwmon # BWMON v5
- const: qcom,sdm845-llcc-bwmon # BWMON v5
interconnects:
maxItems: 1

View File

@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm RPM/RPMh Power domains
maintainers:
- Rajendra Nayak <rnayak@codeaurora.org>
- Bjorn Andersson <andersson@kernel.org>
description:
For RPM/RPMh Power domains, we communicate a performance state to RPM/RPMh
@ -40,6 +40,7 @@ properties:
- qcom,sm6115-rpmpd
- qcom,sm6125-rpmpd
- qcom,sm6350-rpmhpd
- qcom,sm6375-rpmpd
- qcom,sm8150-rpmhpd
- qcom,sm8250-rpmhpd
- qcom,sm8350-rpmhpd

View File

@ -20,6 +20,7 @@ properties:
compatible:
enum:
- qcom,rpmh-stats
- qcom,sdm845-rpmh-stats
- qcom,rpm-stats
# For older RPM firmware versions with fixed offset for the sleep stats
- qcom,apq8084-rpm-stats

View File

@ -129,8 +129,6 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03
#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02
extern void __qcom_scm_init(void);
/* common error codes */
#define QCOM_SCM_V2_EBUSY -12
#define QCOM_SCM_ENOMEM -5

View File

@ -129,7 +129,7 @@ config QCOM_RPMHPD
config QCOM_RPMPD
tristate "Qualcomm RPM Power domain driver"
depends on PM
depends on PM && OF
depends on QCOM_SMD_RPM
select PM_GENERIC_DOMAINS
select PM_GENERIC_DOMAINS_OF

View File

@ -5,6 +5,8 @@
* Author: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, based on
* previous work of Thara Gopinath and msm-4.9 downstream sources.
*/
#include <linux/err.h>
#include <linux/interconnect.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@ -13,6 +15,7 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/sizes.h>
/*
@ -31,33 +34,44 @@
/* Internal sampling clock frequency */
#define HW_TIMER_HZ 19200000
#define BWMON_GLOBAL_IRQ_STATUS 0x0
#define BWMON_GLOBAL_IRQ_CLEAR 0x8
#define BWMON_GLOBAL_IRQ_ENABLE 0xc
#define BWMON_GLOBAL_IRQ_ENABLE_ENABLE BIT(0)
#define BWMON_V4_GLOBAL_IRQ_CLEAR 0x008
#define BWMON_V4_GLOBAL_IRQ_ENABLE 0x00c
/*
* All values here and further are matching regmap fields, so without absolute
* register offsets.
*/
#define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE BIT(0)
#define BWMON_IRQ_STATUS 0x100
#define BWMON_IRQ_STATUS_ZONE_SHIFT 4
#define BWMON_IRQ_CLEAR 0x108
#define BWMON_IRQ_ENABLE 0x10c
#define BWMON_IRQ_ENABLE_ZONE1_SHIFT 5
#define BWMON_IRQ_ENABLE_ZONE2_SHIFT 6
#define BWMON_IRQ_ENABLE_ZONE3_SHIFT 7
#define BWMON_IRQ_ENABLE_MASK (BIT(BWMON_IRQ_ENABLE_ZONE1_SHIFT) | \
BIT(BWMON_IRQ_ENABLE_ZONE3_SHIFT))
#define BWMON_V4_IRQ_STATUS 0x100
#define BWMON_V4_IRQ_CLEAR 0x108
#define BWMON_ENABLE 0x2a0
#define BWMON_V4_IRQ_ENABLE 0x10c
#define BWMON_IRQ_ENABLE_MASK (BIT(1) | BIT(3))
#define BWMON_V5_IRQ_STATUS 0x000
#define BWMON_V5_IRQ_CLEAR 0x008
#define BWMON_V5_IRQ_ENABLE 0x00c
#define BWMON_V4_ENABLE 0x2a0
#define BWMON_V5_ENABLE 0x010
#define BWMON_ENABLE_ENABLE BIT(0)
#define BWMON_CLEAR 0x2a4
#define BWMON_V4_CLEAR 0x2a4
#define BWMON_V5_CLEAR 0x014
#define BWMON_CLEAR_CLEAR BIT(0)
#define BWMON_CLEAR_CLEAR_ALL BIT(1)
#define BWMON_SAMPLE_WINDOW 0x2a8
#define BWMON_THRESHOLD_HIGH 0x2ac
#define BWMON_THRESHOLD_MED 0x2b0
#define BWMON_THRESHOLD_LOW 0x2b4
#define BWMON_V4_SAMPLE_WINDOW 0x2a8
#define BWMON_V5_SAMPLE_WINDOW 0x020
#define BWMON_ZONE_ACTIONS 0x2b8
#define BWMON_V4_THRESHOLD_HIGH 0x2ac
#define BWMON_V4_THRESHOLD_MED 0x2b0
#define BWMON_V4_THRESHOLD_LOW 0x2b4
#define BWMON_V5_THRESHOLD_HIGH 0x024
#define BWMON_V5_THRESHOLD_MED 0x028
#define BWMON_V5_THRESHOLD_LOW 0x02c
#define BWMON_V4_ZONE_ACTIONS 0x2b8
#define BWMON_V5_ZONE_ACTIONS 0x030
/*
* Actions to perform on some zone 'z' when current zone hits the threshold:
* Increment counter of zone 'z'
@ -83,55 +97,244 @@
BWMON_ZONE_ACTIONS_CLEAR(2) | \
BWMON_ZONE_ACTIONS_CLEAR(1) | \
BWMON_ZONE_ACTIONS_CLEAR(0))
/* Value for BWMON_ZONE_ACTIONS */
#define BWMON_ZONE_ACTIONS_DEFAULT (BWMON_ZONE_ACTIONS_ZONE0 | \
BWMON_ZONE_ACTIONS_ZONE1 << 8 | \
BWMON_ZONE_ACTIONS_ZONE2 << 16 | \
BWMON_ZONE_ACTIONS_ZONE3 << 24)
/*
* There is no clear documentation/explanation of BWMON_THRESHOLD_COUNT
* There is no clear documentation/explanation of BWMON_V4_THRESHOLD_COUNT
* register. Based on observations, this is number of times one threshold has to
* be reached, to trigger interrupt in given zone.
*
* 0xff are maximum values meant to ignore the zones 0 and 2.
*/
#define BWMON_THRESHOLD_COUNT 0x2bc
#define BWMON_THRESHOLD_COUNT_ZONE1_SHIFT 8
#define BWMON_THRESHOLD_COUNT_ZONE2_SHIFT 16
#define BWMON_THRESHOLD_COUNT_ZONE3_SHIFT 24
#define BWMON_V4_THRESHOLD_COUNT 0x2bc
#define BWMON_V5_THRESHOLD_COUNT 0x034
#define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff
#define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff
/* BWMONv4 count registers use count unit of 64 kB */
#define BWMON_COUNT_UNIT_KB 64
#define BWMON_ZONE_COUNT 0x2d8
#define BWMON_ZONE_MAX(zone) (0x2e0 + 4 * (zone))
#define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone))
#define BWMON_V5_ZONE_MAX(zone) (0x044 + 4 * (zone))
/* Quirks for specific BWMON types */
#define BWMON_HAS_GLOBAL_IRQ BIT(0)
#define BWMON_NEEDS_FORCE_CLEAR BIT(1)
enum bwmon_fields {
F_GLOBAL_IRQ_CLEAR,
F_GLOBAL_IRQ_ENABLE,
F_IRQ_STATUS,
F_IRQ_CLEAR,
F_IRQ_ENABLE,
F_ENABLE,
F_CLEAR,
F_SAMPLE_WINDOW,
F_THRESHOLD_HIGH,
F_THRESHOLD_MED,
F_THRESHOLD_LOW,
F_ZONE_ACTIONS_ZONE0,
F_ZONE_ACTIONS_ZONE1,
F_ZONE_ACTIONS_ZONE2,
F_ZONE_ACTIONS_ZONE3,
F_THRESHOLD_COUNT_ZONE0,
F_THRESHOLD_COUNT_ZONE1,
F_THRESHOLD_COUNT_ZONE2,
F_THRESHOLD_COUNT_ZONE3,
F_ZONE0_MAX,
F_ZONE1_MAX,
F_ZONE2_MAX,
F_ZONE3_MAX,
F_NUM_FIELDS
};
struct icc_bwmon_data {
unsigned int sample_ms;
unsigned int count_unit_kb; /* kbytes */
unsigned int default_highbw_kbps;
unsigned int default_medbw_kbps;
unsigned int default_lowbw_kbps;
u8 zone1_thres_count;
u8 zone3_thres_count;
unsigned int quirks;
const struct regmap_config *regmap_cfg;
const struct reg_field *regmap_fields;
};
struct icc_bwmon {
struct device *dev;
void __iomem *base;
const struct icc_bwmon_data *data;
int irq;
unsigned int default_lowbw_kbps;
unsigned int sample_ms;
struct regmap *regmap;
struct regmap_field *regs[F_NUM_FIELDS];
unsigned int max_bw_kbps;
unsigned int min_bw_kbps;
unsigned int target_kbps;
unsigned int current_kbps;
};
static void bwmon_clear_counters(struct icc_bwmon *bwmon)
/* BWMON v4 */
static const struct reg_field msm8998_bwmon_reg_fields[] = {
[F_GLOBAL_IRQ_CLEAR] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
[F_GLOBAL_IRQ_ENABLE] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
[F_IRQ_STATUS] = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
[F_IRQ_CLEAR] = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
[F_IRQ_ENABLE] = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
/* F_ENABLE covers entire register to disable other features */
[F_ENABLE] = REG_FIELD(BWMON_V4_ENABLE, 0, 31),
[F_CLEAR] = REG_FIELD(BWMON_V4_CLEAR, 0, 1),
[F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23),
[F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11),
[F_THRESHOLD_MED] = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11),
[F_THRESHOLD_LOW] = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11),
[F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7),
[F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15),
[F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23),
[F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31),
[F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7),
[F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15),
[F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23),
[F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31),
[F_ZONE0_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11),
[F_ZONE1_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11),
[F_ZONE2_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11),
[F_ZONE3_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11),
};
static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] = {
regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
};
static const struct regmap_access_table msm8998_bwmon_reg_read_table = {
.no_ranges = msm8998_bwmon_reg_noread_ranges,
.n_no_ranges = ARRAY_SIZE(msm8998_bwmon_reg_noread_ranges),
};
static const struct regmap_range msm8998_bwmon_reg_volatile_ranges[] = {
regmap_reg_range(BWMON_V4_IRQ_STATUS, BWMON_V4_IRQ_STATUS),
regmap_reg_range(BWMON_V4_ZONE_MAX(0), BWMON_V4_ZONE_MAX(3)),
};
static const struct regmap_access_table msm8998_bwmon_reg_volatile_table = {
.yes_ranges = msm8998_bwmon_reg_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(msm8998_bwmon_reg_volatile_ranges),
};
/*
* Fill the cache for non-readable registers only as rest does not really
* matter and can be read from the device.
*/
static const struct reg_default msm8998_bwmon_reg_defaults[] = {
{ BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
{ BWMON_V4_IRQ_CLEAR, 0x0 },
{ BWMON_V4_CLEAR, 0x0 },
};
static const struct regmap_config msm8998_bwmon_regmap_cfg = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
/*
* No concurrent access expected - driver has one interrupt handler,
* regmap is not shared, no driver or user-space API.
*/
.disable_locking = true,
.rd_table = &msm8998_bwmon_reg_read_table,
.volatile_table = &msm8998_bwmon_reg_volatile_table,
.reg_defaults = msm8998_bwmon_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(msm8998_bwmon_reg_defaults),
/*
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
.cache_type = REGCACHE_RBTREE,
};
/* BWMON v5 */
static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = {
[F_GLOBAL_IRQ_CLEAR] = {},
[F_GLOBAL_IRQ_ENABLE] = {},
[F_IRQ_STATUS] = REG_FIELD(BWMON_V5_IRQ_STATUS, 0, 3),
[F_IRQ_CLEAR] = REG_FIELD(BWMON_V5_IRQ_CLEAR, 0, 3),
[F_IRQ_ENABLE] = REG_FIELD(BWMON_V5_IRQ_ENABLE, 0, 3),
/* F_ENABLE covers entire register to disable other features */
[F_ENABLE] = REG_FIELD(BWMON_V5_ENABLE, 0, 31),
[F_CLEAR] = REG_FIELD(BWMON_V5_CLEAR, 0, 1),
[F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V5_SAMPLE_WINDOW, 0, 19),
[F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V5_THRESHOLD_HIGH, 0, 11),
[F_THRESHOLD_MED] = REG_FIELD(BWMON_V5_THRESHOLD_MED, 0, 11),
[F_THRESHOLD_LOW] = REG_FIELD(BWMON_V5_THRESHOLD_LOW, 0, 11),
[F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 0, 7),
[F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 8, 15),
[F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 16, 23),
[F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 24, 31),
[F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 0, 7),
[F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 8, 15),
[F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 16, 23),
[F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 24, 31),
[F_ZONE0_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(0), 0, 11),
[F_ZONE1_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(1), 0, 11),
[F_ZONE2_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(2), 0, 11),
[F_ZONE3_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(3), 0, 11),
};
static const struct regmap_range sdm845_llcc_bwmon_reg_noread_ranges[] = {
regmap_reg_range(BWMON_V5_IRQ_CLEAR, BWMON_V5_IRQ_CLEAR),
regmap_reg_range(BWMON_V5_CLEAR, BWMON_V5_CLEAR),
};
static const struct regmap_access_table sdm845_llcc_bwmon_reg_read_table = {
.no_ranges = sdm845_llcc_bwmon_reg_noread_ranges,
.n_no_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_noread_ranges),
};
static const struct regmap_range sdm845_llcc_bwmon_reg_volatile_ranges[] = {
regmap_reg_range(BWMON_V5_IRQ_STATUS, BWMON_V5_IRQ_STATUS),
regmap_reg_range(BWMON_V5_ZONE_MAX(0), BWMON_V5_ZONE_MAX(3)),
};
static const struct regmap_access_table sdm845_llcc_bwmon_reg_volatile_table = {
.yes_ranges = sdm845_llcc_bwmon_reg_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_volatile_ranges),
};
/*
* Fill the cache for non-readable registers only as rest does not really
* matter and can be read from the device.
*/
static const struct reg_default sdm845_llcc_bwmon_reg_defaults[] = {
{ BWMON_V5_IRQ_CLEAR, 0x0 },
{ BWMON_V5_CLEAR, 0x0 },
};
static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
/*
* No concurrent access expected - driver has one interrupt handler,
* regmap is not shared, no driver or user-space API.
*/
.disable_locking = true,
.rd_table = &sdm845_llcc_bwmon_reg_read_table,
.volatile_table = &sdm845_llcc_bwmon_reg_volatile_table,
.reg_defaults = sdm845_llcc_bwmon_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(sdm845_llcc_bwmon_reg_defaults),
/*
* Cache is necessary for using regmap fields with non-readable
* registers.
*/
.cache_type = REGCACHE_RBTREE,
};
static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
{
unsigned int val = BWMON_CLEAR_CLEAR;
if (clear_all)
val |= BWMON_CLEAR_CLEAR_ALL;
/*
* Clear counters. The order and barriers are
* important. Quoting downstream Qualcomm msm-4.9 tree:
@ -140,7 +343,9 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon)
* region. So, we need to make sure the counter clear is completed
* before we try to clear the IRQ or do any other counter operations.
*/
writel(BWMON_CLEAR_CLEAR, bwmon->base + BWMON_CLEAR);
regmap_field_force_write(bwmon->regs[F_CLEAR], val);
if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
regmap_field_force_write(bwmon->regs[F_CLEAR], 0);
}
static void bwmon_clear_irq(struct icc_bwmon *bwmon)
@ -161,76 +366,91 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon)
* clearing here so that local writes don't happen before the
* interrupt is cleared.
*/
writel(BWMON_IRQ_ENABLE_MASK, bwmon->base + BWMON_IRQ_CLEAR);
writel(BIT(0), bwmon->base + BWMON_GLOBAL_IRQ_CLEAR);
regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK);
if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0);
if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR],
BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
}
static void bwmon_disable(struct icc_bwmon *bwmon)
{
/* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
writel(0x0, bwmon->base + BWMON_GLOBAL_IRQ_ENABLE);
writel(0x0, bwmon->base + BWMON_IRQ_ENABLE);
if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0);
regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0);
/*
* Disable bwmon. Must happen before bwmon_clear_irq() to avoid spurious
* IRQ.
*/
writel(0x0, bwmon->base + BWMON_ENABLE);
regmap_field_write(bwmon->regs[F_ENABLE], 0x0);
}
static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
{
/* Enable interrupts */
writel(BWMON_GLOBAL_IRQ_ENABLE_ENABLE,
bwmon->base + BWMON_GLOBAL_IRQ_ENABLE);
writel(irq_enable, bwmon->base + BWMON_IRQ_ENABLE);
if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE],
BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable);
/* Enable bwmon */
writel(BWMON_ENABLE_ENABLE, bwmon->base + BWMON_ENABLE);
regmap_field_write(bwmon->regs[F_ENABLE], BWMON_ENABLE_ENABLE);
}
static unsigned int bwmon_kbps_to_count(unsigned int kbps)
{
return kbps / BWMON_COUNT_UNIT_KB;
}
static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg,
static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon,
unsigned int kbps)
{
return kbps / bwmon->data->count_unit_kb;
}
static void bwmon_set_threshold(struct icc_bwmon *bwmon,
struct regmap_field *reg, unsigned int kbps)
{
unsigned int thres;
thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->sample_ms,
MSEC_PER_SEC);
writel_relaxed(thres, bwmon->base + reg);
thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
bwmon->data->sample_ms, MSEC_PER_SEC);
regmap_field_write(reg, thres);
}
static void bwmon_start(struct icc_bwmon *bwmon,
const struct icc_bwmon_data *data)
static void bwmon_start(struct icc_bwmon *bwmon)
{
unsigned int thres_count;
const struct icc_bwmon_data *data = bwmon->data;
int window;
bwmon_clear_counters(bwmon);
bwmon_clear_counters(bwmon, true);
window = mult_frac(bwmon->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
/* Maximum sampling window: 0xfffff */
writel_relaxed(window, bwmon->base + BWMON_SAMPLE_WINDOW);
window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
/* Maximum sampling window: 0xffffff for v4 and 0xfffff for v5 */
regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window);
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH,
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH],
data->default_highbw_kbps);
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED,
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED],
data->default_medbw_kbps);
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_LOW,
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW],
data->default_lowbw_kbps);
thres_count = data->zone3_thres_count << BWMON_THRESHOLD_COUNT_ZONE3_SHIFT |
BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT << BWMON_THRESHOLD_COUNT_ZONE2_SHIFT |
data->zone1_thres_count << BWMON_THRESHOLD_COUNT_ZONE1_SHIFT |
BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT;
writel_relaxed(thres_count, bwmon->base + BWMON_THRESHOLD_COUNT);
writel_relaxed(BWMON_ZONE_ACTIONS_DEFAULT,
bwmon->base + BWMON_ZONE_ACTIONS);
/* Write barriers in bwmon_clear_irq() */
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE0],
BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT);
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE1],
data->zone1_thres_count);
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE2],
BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT);
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE3],
data->zone3_thres_count);
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE0],
BWMON_ZONE_ACTIONS_ZONE0);
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE1],
BWMON_ZONE_ACTIONS_ZONE1);
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE2],
BWMON_ZONE_ACTIONS_ZONE2);
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE3],
BWMON_ZONE_ACTIONS_ZONE3);
bwmon_clear_irq(bwmon);
bwmon_enable(bwmon, BWMON_IRQ_ENABLE_MASK);
@ -242,7 +462,9 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id)
unsigned int status, max;
int zone;
status = readl(bwmon->base + BWMON_IRQ_STATUS);
if (regmap_field_read(bwmon->regs[F_IRQ_STATUS], &status))
return IRQ_NONE;
status &= BWMON_IRQ_ENABLE_MASK;
if (!status) {
/*
@ -259,15 +481,18 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id)
bwmon_disable(bwmon);
zone = get_bitmask_order(status >> BWMON_IRQ_STATUS_ZONE_SHIFT) - 1;
zone = get_bitmask_order(status) - 1;
/*
* Zone max bytes count register returns count units within sampling
* window. Downstream kernel for BWMONv4 (called BWMON type 2 in
* downstream) always increments the max bytes count by one.
*/
max = readl(bwmon->base + BWMON_ZONE_MAX(zone)) + 1;
max *= BWMON_COUNT_UNIT_KB;
bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->sample_ms);
if (regmap_field_read(bwmon->regs[F_ZONE0_MAX + zone], &max))
return IRQ_NONE;
max += 1;
max *= bwmon->data->count_unit_kb;
bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
return IRQ_WAKE_THREAD;
}
@ -297,16 +522,17 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
up_kbps = bwmon->target_kbps + 1;
if (bwmon->target_kbps >= bwmon->max_bw_kbps)
irq_enable = BIT(BWMON_IRQ_ENABLE_ZONE1_SHIFT);
irq_enable = BIT(1);
else if (bwmon->target_kbps <= bwmon->min_bw_kbps)
irq_enable = BIT(BWMON_IRQ_ENABLE_ZONE3_SHIFT);
irq_enable = BIT(3);
else
irq_enable = BWMON_IRQ_ENABLE_MASK;
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, up_kbps);
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, down_kbps);
/* Write barriers in bwmon_clear_counters() */
bwmon_clear_counters(bwmon);
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH],
up_kbps);
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED],
down_kbps);
bwmon_clear_counters(bwmon, false);
bwmon_clear_irq(bwmon);
bwmon_enable(bwmon, irq_enable);
@ -324,25 +550,47 @@ out:
return IRQ_HANDLED;
}
static int bwmon_init_regmap(struct platform_device *pdev,
struct icc_bwmon *bwmon)
{
struct device *dev = &pdev->dev;
void __iomem *base;
struct regmap *map;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
return dev_err_probe(dev, PTR_ERR(base),
"failed to map bwmon registers\n");
map = devm_regmap_init_mmio(dev, base, bwmon->data->regmap_cfg);
if (IS_ERR(map))
return dev_err_probe(dev, PTR_ERR(map),
"failed to initialize regmap\n");
BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
return devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
bwmon->data->regmap_fields,
F_NUM_FIELDS);
}
static int bwmon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct dev_pm_opp *opp;
struct icc_bwmon *bwmon;
const struct icc_bwmon_data *data;
int ret;
bwmon = devm_kzalloc(dev, sizeof(*bwmon), GFP_KERNEL);
if (!bwmon)
return -ENOMEM;
data = of_device_get_match_data(dev);
bwmon->data = of_device_get_match_data(dev);
bwmon->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(bwmon->base)) {
dev_err(dev, "failed to map bwmon registers\n");
return PTR_ERR(bwmon->base);
}
ret = bwmon_init_regmap(pdev, bwmon);
if (ret)
return ret;
bwmon->irq = platform_get_irq(pdev, 0);
if (bwmon->irq < 0)
@ -362,8 +610,6 @@ static int bwmon_probe(struct platform_device *pdev)
if (IS_ERR(opp))
return dev_err_probe(dev, ret, "failed to find min peak bandwidth\n");
bwmon->sample_ms = data->sample_ms;
bwmon->default_lowbw_kbps = data->default_lowbw_kbps;
bwmon->dev = dev;
bwmon_disable(bwmon);
@ -374,7 +620,7 @@ static int bwmon_probe(struct platform_device *pdev)
return dev_err_probe(dev, ret, "failed to request IRQ\n");
platform_set_drvdata(pdev, bwmon);
bwmon_start(bwmon, data);
bwmon_start(bwmon);
return 0;
}
@ -388,18 +634,55 @@ static int bwmon_remove(struct platform_device *pdev)
return 0;
}
/* BWMON v4 */
static const struct icc_bwmon_data msm8998_bwmon_data = {
.sample_ms = 4,
.count_unit_kb = 64,
.default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
.default_medbw_kbps = 512 * 1024, /* 512 MBps */
.default_lowbw_kbps = 0,
.zone1_thres_count = 16,
.zone3_thres_count = 1,
.quirks = BWMON_HAS_GLOBAL_IRQ,
.regmap_fields = msm8998_bwmon_reg_fields,
.regmap_cfg = &msm8998_bwmon_regmap_cfg,
};
static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
.sample_ms = 4,
.count_unit_kb = 1024,
.default_highbw_kbps = 800 * 1024, /* 800 MBps */
.default_medbw_kbps = 256 * 1024, /* 256 MBps */
.default_lowbw_kbps = 0,
.zone1_thres_count = 16,
.zone3_thres_count = 1,
.regmap_fields = sdm845_llcc_bwmon_reg_fields,
.regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
};
static const struct icc_bwmon_data sc7280_llcc_bwmon_data = {
.sample_ms = 4,
.count_unit_kb = 64,
.default_highbw_kbps = 800 * 1024, /* 800 MBps */
.default_medbw_kbps = 256 * 1024, /* 256 MBps */
.default_lowbw_kbps = 0,
.zone1_thres_count = 16,
.zone3_thres_count = 1,
.quirks = BWMON_NEEDS_FORCE_CLEAR,
.regmap_fields = sdm845_llcc_bwmon_reg_fields,
.regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
};
static const struct of_device_id bwmon_of_match[] = {
{ .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
{
.compatible = "qcom,msm8998-bwmon",
.data = &msm8998_bwmon_data
}, {
.compatible = "qcom,sdm845-llcc-bwmon",
.data = &sdm845_llcc_bwmon_data
}, {
.compatible = "qcom,sc7280-llcc-bwmon",
.data = &sc7280_llcc_bwmon_data
},
{}
};
MODULE_DEVICE_TABLE(of, bwmon_of_match);

View File

@ -104,6 +104,7 @@ struct qcom_llcc_config {
int size;
bool need_llcc_cfg;
const u32 *reg_offset;
const struct llcc_edac_reg_offset *edac_reg_offset;
};
enum llcc_reg_offset {
@ -296,12 +297,68 @@ static const struct llcc_slice_config sm8450_data[] = {
{LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 },
};
static const u32 llcc_v1_2_reg_offset[] = {
static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
.trp_ecc_error_status0 = 0x20344,
.trp_ecc_error_status1 = 0x20348,
.trp_ecc_sb_err_syn0 = 0x2304c,
.trp_ecc_db_err_syn0 = 0x20370,
.trp_ecc_error_cntr_clear = 0x20440,
.trp_interrupt_0_status = 0x20480,
.trp_interrupt_0_clear = 0x20484,
.trp_interrupt_0_enable = 0x20488,
/* LLCC Common registers */
.cmn_status0 = 0x3000c,
.cmn_interrupt_0_enable = 0x3001c,
.cmn_interrupt_2_enable = 0x3003c,
/* LLCC DRP registers */
.drp_ecc_error_cfg = 0x40000,
.drp_ecc_error_cntr_clear = 0x40004,
.drp_interrupt_status = 0x41000,
.drp_interrupt_clear = 0x41008,
.drp_interrupt_enable = 0x4100c,
.drp_ecc_error_status0 = 0x42044,
.drp_ecc_error_status1 = 0x42048,
.drp_ecc_sb_err_syn0 = 0x4204c,
.drp_ecc_db_err_syn0 = 0x42070,
};
static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = {
.trp_ecc_error_status0 = 0x20344,
.trp_ecc_error_status1 = 0x20348,
.trp_ecc_sb_err_syn0 = 0x2034c,
.trp_ecc_db_err_syn0 = 0x20370,
.trp_ecc_error_cntr_clear = 0x20440,
.trp_interrupt_0_status = 0x20480,
.trp_interrupt_0_clear = 0x20484,
.trp_interrupt_0_enable = 0x20488,
/* LLCC Common registers */
.cmn_status0 = 0x3400c,
.cmn_interrupt_0_enable = 0x3401c,
.cmn_interrupt_2_enable = 0x3403c,
/* LLCC DRP registers */
.drp_ecc_error_cfg = 0x50000,
.drp_ecc_error_cntr_clear = 0x50004,
.drp_interrupt_status = 0x50020,
.drp_interrupt_clear = 0x50028,
.drp_interrupt_enable = 0x5002c,
.drp_ecc_error_status0 = 0x520f4,
.drp_ecc_error_status1 = 0x520f8,
.drp_ecc_sb_err_syn0 = 0x520fc,
.drp_ecc_db_err_syn0 = 0x52120,
};
/* LLCC register offset starting from v1.0.0 */
static const u32 llcc_v1_reg_offset[] = {
[LLCC_COMMON_HW_INFO] = 0x00030000,
[LLCC_COMMON_STATUS0] = 0x0003000c,
};
static const u32 llcc_v21_reg_offset[] = {
/* LLCC register offset starting from v2.0.1 */
static const u32 llcc_v2_1_reg_offset[] = {
[LLCC_COMMON_HW_INFO] = 0x00034000,
[LLCC_COMMON_STATUS0] = 0x0003400c,
};
@ -310,70 +367,80 @@ static const struct qcom_llcc_config sc7180_cfg = {
.sct_data = sc7180_data,
.size = ARRAY_SIZE(sc7180_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sc7280_cfg = {
.sct_data = sc7280_data,
.size = ARRAY_SIZE(sc7280_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sc8180x_cfg = {
.sct_data = sc8180x_data,
.size = ARRAY_SIZE(sc8180x_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sc8280xp_cfg = {
.sct_data = sc8280xp_data,
.size = ARRAY_SIZE(sc8280xp_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sdm845_cfg = {
.sct_data = sdm845_data,
.size = ARRAY_SIZE(sdm845_data),
.need_llcc_cfg = false,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sm6350_cfg = {
.sct_data = sm6350_data,
.size = ARRAY_SIZE(sm6350_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sm8150_cfg = {
.sct_data = sm8150_data,
.size = ARRAY_SIZE(sm8150_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sm8250_cfg = {
.sct_data = sm8250_data,
.size = ARRAY_SIZE(sm8250_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sm8350_cfg = {
.sct_data = sm8350_data,
.size = ARRAY_SIZE(sm8350_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v1_2_reg_offset,
.reg_offset = llcc_v1_reg_offset,
.edac_reg_offset = &llcc_v1_edac_reg_offset,
};
static const struct qcom_llcc_config sm8450_cfg = {
.sct_data = sm8450_data,
.size = ARRAY_SIZE(sm8450_data),
.need_llcc_cfg = true,
.reg_offset = llcc_v21_reg_offset,
.reg_offset = llcc_v2_1_reg_offset,
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
};
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
@ -774,6 +841,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
drv_data->cfg = llcc_cfg;
drv_data->cfg_size = sz;
drv_data->edac_reg_offset = cfg->edac_reg_offset;
mutex_init(&drv_data->lock);
platform_set_drvdata(pdev, drv_data);

View File

@ -246,6 +246,14 @@ static const struct stats_config rpm_data_dba0 = {
.subsystem_stats_in_smem = false,
};
static const struct stats_config rpmh_data_sdm845 = {
.stats_offset = 0x48,
.num_records = 2,
.appended_stats_avail = false,
.dynamic_offset = false,
.subsystem_stats_in_smem = true,
};
static const struct stats_config rpmh_data = {
.stats_offset = 0x48,
.num_records = 3,
@ -261,6 +269,7 @@ static const struct of_device_id qcom_stats_table[] = {
{ .compatible = "qcom,msm8974-rpm-stats", .data = &rpm_data_dba0 },
{ .compatible = "qcom,rpm-stats", .data = &rpm_data },
{ .compatible = "qcom,rpmh-stats", .data = &rpmh_data },
{ .compatible = "qcom,sdm845-rpmh-stats", .data = &rpmh_data_sdm845 },
{ }
};
MODULE_DEVICE_TABLE(of, qcom_stats_table);

View File

@ -57,11 +57,11 @@ do { \
#define TLV_TYPE_SIZE sizeof(u8)
#define OPTIONAL_TLV_TYPE_START 0x10
static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf,
static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
const void *in_c_struct, u32 out_buf_len,
int enc_level);
static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
const void *in_buf, u32 in_buf_len, int dec_level);
/**
@ -76,10 +76,10 @@ static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
*
* Return: struct info of the next element that can be encoded.
*/
static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array,
int level)
static const struct qmi_elem_info *
skip_to_next_elem(const struct qmi_elem_info *ei_array, int level)
{
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
u8 tlv_type;
if (level > 1) {
@ -101,11 +101,11 @@ static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array,
*
* Return: Expected minimum length of the QMI message or 0 on error.
*/
static int qmi_calc_min_msg_len(struct qmi_elem_info *ei_array,
static int qmi_calc_min_msg_len(const struct qmi_elem_info *ei_array,
int level)
{
int min_msg_len = 0;
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
if (!ei_array)
return min_msg_len;
@ -194,13 +194,13 @@ static int qmi_encode_basic_elem(void *buf_dst, const void *buf_src,
* Return: The number of bytes of encoded information on success or negative
* errno on error.
*/
static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array,
static int qmi_encode_struct_elem(const struct qmi_elem_info *ei_array,
void *buf_dst, const void *buf_src,
u32 elem_len, u32 out_buf_len,
int enc_level)
{
int i, rc, encoded_bytes = 0;
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
for (i = 0; i < elem_len; i++) {
rc = qmi_encode(temp_ei->ei_array, buf_dst, buf_src,
@ -233,13 +233,13 @@ static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array,
* Return: The number of bytes of encoded information on success or negative
* errno on error.
*/
static int qmi_encode_string_elem(struct qmi_elem_info *ei_array,
static int qmi_encode_string_elem(const struct qmi_elem_info *ei_array,
void *buf_dst, const void *buf_src,
u32 out_buf_len, int enc_level)
{
int rc;
int encoded_bytes = 0;
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
u32 string_len = 0;
u32 string_len_sz = 0;
@ -289,11 +289,11 @@ static int qmi_encode_string_elem(struct qmi_elem_info *ei_array,
* Return: The number of bytes of encoded information on success or negative
* errno on error.
*/
static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf,
static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
const void *in_c_struct, u32 out_buf_len,
int enc_level)
{
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
u8 opt_flag_value = 0;
u32 data_len_value = 0, data_len_sz;
u8 *buf_dst = (u8 *)out_buf;
@ -468,13 +468,13 @@ static int qmi_decode_basic_elem(void *buf_dst, const void *buf_src,
* Return: The total size of the decoded data elements on success, negative
* errno on error.
*/
static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array,
static int qmi_decode_struct_elem(const struct qmi_elem_info *ei_array,
void *buf_dst, const void *buf_src,
u32 elem_len, u32 tlv_len,
int dec_level)
{
int i, rc, decoded_bytes = 0;
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
for (i = 0; i < elem_len && decoded_bytes < tlv_len; i++) {
rc = qmi_decode(temp_ei->ei_array, buf_dst, buf_src,
@ -514,7 +514,7 @@ static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array,
* Return: The total size of the decoded data elements on success, negative
* errno on error.
*/
static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array,
void *buf_dst, const void *buf_src,
u32 tlv_len, int dec_level)
{
@ -522,7 +522,7 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
int decoded_bytes = 0;
u32 string_len = 0;
u32 string_len_sz = 0;
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
if (dec_level == 1) {
string_len = tlv_len;
@ -564,10 +564,10 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
*
* Return: Pointer to struct info, if found
*/
static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array,
static const struct qmi_elem_info *find_ei(const struct qmi_elem_info *ei_array,
u32 type)
{
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
while (temp_ei->data_type != QMI_EOTI) {
if (temp_ei->tlv_type == (u8)type)
@ -590,11 +590,11 @@ static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array,
* Return: The number of bytes of decoded information on success, negative
* errno on error.
*/
static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
const void *in_buf, u32 in_buf_len,
int dec_level)
{
struct qmi_elem_info *temp_ei = ei_array;
const struct qmi_elem_info *temp_ei = ei_array;
u8 opt_flag_value = 1;
u32 data_len_value = 0, data_len_sz = 0;
u8 *buf_dst = out_c_struct;
@ -713,7 +713,7 @@ static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
* Return: Buffer with encoded message, or negative ERR_PTR() on error
*/
void *qmi_encode_message(int type, unsigned int msg_id, size_t *len,
unsigned int txn_id, struct qmi_elem_info *ei,
unsigned int txn_id, const struct qmi_elem_info *ei,
const void *c_struct)
{
struct qmi_header *hdr;
@ -767,7 +767,7 @@ EXPORT_SYMBOL(qmi_encode_message);
* errno on error.
*/
int qmi_decode_message(const void *buf, size_t len,
struct qmi_elem_info *ei, void *c_struct)
const struct qmi_elem_info *ei, void *c_struct)
{
if (!ei)
return -EINVAL;
@ -781,7 +781,7 @@ int qmi_decode_message(const void *buf, size_t len,
EXPORT_SYMBOL(qmi_decode_message);
/* Common header in all QMI responses */
struct qmi_elem_info qmi_response_type_v01_ei[] = {
const struct qmi_elem_info qmi_response_type_v01_ei[] = {
{
.data_type = QMI_SIGNED_2_BYTE_ENUM,
.elem_len = 1,

View File

@ -305,7 +305,7 @@ EXPORT_SYMBOL(qmi_add_server);
* Return: Transaction id on success, negative errno on failure.
*/
int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
struct qmi_elem_info *ei, void *c_struct)
const struct qmi_elem_info *ei, void *c_struct)
{
int ret;
@ -736,7 +736,8 @@ EXPORT_SYMBOL(qmi_handle_release);
static ssize_t qmi_send_message(struct qmi_handle *qmi,
struct sockaddr_qrtr *sq, struct qmi_txn *txn,
int type, int msg_id, size_t len,
struct qmi_elem_info *ei, const void *c_struct)
const struct qmi_elem_info *ei,
const void *c_struct)
{
struct msghdr msghdr = {};
struct kvec iv;
@ -787,7 +788,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi,
*/
ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
struct qmi_txn *txn, int msg_id, size_t len,
struct qmi_elem_info *ei, const void *c_struct)
const struct qmi_elem_info *ei, const void *c_struct)
{
return qmi_send_message(qmi, sq, txn, QMI_REQUEST, msg_id, len, ei,
c_struct);
@ -808,7 +809,7 @@ EXPORT_SYMBOL(qmi_send_request);
*/
ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
struct qmi_txn *txn, int msg_id, size_t len,
struct qmi_elem_info *ei, const void *c_struct)
const struct qmi_elem_info *ei, const void *c_struct)
{
return qmi_send_message(qmi, sq, txn, QMI_RESPONSE, msg_id, len, ei,
c_struct);
@ -827,7 +828,8 @@ EXPORT_SYMBOL(qmi_send_response);
* Return: 0 on success, negative errno on failure.
*/
ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
int msg_id, size_t len, struct qmi_elem_info *ei,
int msg_id, size_t len,
const struct qmi_elem_info *ei,
const void *c_struct)
{
struct qmi_txn txn;

View File

@ -29,6 +29,7 @@
#define RPMPD_RWLM 0x6d6c7772
#define RPMPD_RWSC 0x63737772
#define RPMPD_RWSM 0x6d737772
#define RPMPD_RWGX 0x78677772
/* Operation Keys */
#define KEY_CORNER 0x6e726f63 /* corn */
@ -433,6 +434,26 @@ static const struct rpmpd_desc sm6125_desc = {
.max_state = RPM_SMD_LEVEL_BINNING,
};
DEFINE_RPMPD_PAIR(sm6375, vddgx, vddgx_ao, RWGX, LEVEL, 0);
static struct rpmpd *sm6375_rpmpds[] = {
[SM6375_VDDCX] = &sm6125_vddcx,
[SM6375_VDDCX_AO] = &sm6125_vddcx_ao,
[SM6375_VDDCX_VFL] = &sm6125_vddcx_vfl,
[SM6375_VDDMX] = &sm6125_vddmx,
[SM6375_VDDMX_AO] = &sm6125_vddmx_ao,
[SM6375_VDDMX_VFL] = &sm6125_vddmx_vfl,
[SM6375_VDDGX] = &sm6375_vddgx,
[SM6375_VDDGX_AO] = &sm6375_vddgx_ao,
[SM6375_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
[SM6375_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
};
static const struct rpmpd_desc sm6375_desc = {
.rpmpds = sm6375_rpmpds,
.num_pds = ARRAY_SIZE(sm6375_rpmpds),
.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
};
static struct rpmpd *qcm2290_rpmpds[] = {
[QCM2290_VDDCX] = &sm6115_vddcx,
[QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
@ -466,6 +487,7 @@ static const struct of_device_id rpmpd_match_table[] = {
{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
{ .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
{ }
};
MODULE_DEVICE_TABLE(of, rpmpd_match_table);

View File

@ -136,6 +136,7 @@ static void qcom_smem_state_release(struct kref *ref)
struct qcom_smem_state *state = container_of(ref, struct qcom_smem_state, refcount);
list_del(&state->list);
of_node_put(state->of_node);
kfree(state);
}
@ -205,7 +206,7 @@ struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node,
kref_init(&state->refcount);
state->of_node = of_node;
state->of_node = of_node_get(of_node);
state->ops = *ops;
state->priv = priv;

View File

@ -526,7 +526,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
for (id = 0; id < smsm->num_hosts; id++) {
ret = smsm_parse_ipc(smsm, id);
if (ret < 0)
return ret;
goto out_put;
}
/* Acquire the main SMSM state vector */
@ -534,13 +534,14 @@ static int qcom_smsm_probe(struct platform_device *pdev)
smsm->num_entries * sizeof(u32));
if (ret < 0 && ret != -EEXIST) {
dev_err(&pdev->dev, "unable to allocate shared state entry\n");
return ret;
goto out_put;
}
states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL);
if (IS_ERR(states)) {
dev_err(&pdev->dev, "Unable to acquire shared state entry\n");
return PTR_ERR(states);
ret = PTR_ERR(states);
goto out_put;
}
/* Acquire the list of interrupt mask vectors */
@ -548,13 +549,14 @@ static int qcom_smsm_probe(struct platform_device *pdev)
ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, size);
if (ret < 0 && ret != -EEXIST) {
dev_err(&pdev->dev, "unable to allocate smsm interrupt mask\n");
return ret;
goto out_put;
}
intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL);
if (IS_ERR(intr_mask)) {
dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n");
return PTR_ERR(intr_mask);
ret = PTR_ERR(intr_mask);
goto out_put;
}
/* Setup the reference to the local state bits */
@ -565,7 +567,8 @@ static int qcom_smsm_probe(struct platform_device *pdev)
smsm->state = qcom_smem_state_register(local_node, &smsm_state_ops, smsm);
if (IS_ERR(smsm->state)) {
dev_err(smsm->dev, "failed to register qcom_smem_state\n");
return PTR_ERR(smsm->state);
ret = PTR_ERR(smsm->state);
goto out_put;
}
/* Register handlers for remote processor entries of interest. */
@ -595,16 +598,19 @@ static int qcom_smsm_probe(struct platform_device *pdev)
}
platform_set_drvdata(pdev, smsm);
of_node_put(local_node);
return 0;
unwind_interfaces:
of_node_put(node);
for (id = 0; id < smsm->num_entries; id++)
if (smsm->entries[id].domain)
irq_domain_remove(smsm->entries[id].domain);
qcom_smem_state_unregister(smsm->state);
out_put:
of_node_put(local_node);
return ret;
}

View File

@ -104,6 +104,7 @@ static const char *const pmic_models[] = {
[36] = "PM8009",
[38] = "PM8150C",
[41] = "SMB2351",
[45] = "PM6125",
[47] = "PMK8350",
[48] = "PM8350",
[49] = "PM8350C",
@ -334,6 +335,7 @@ static const struct soc_id soc_id[] = {
{ 482, "SM8450" },
{ 487, "SC7280" },
{ 495, "SC7180P" },
{ 507, "SM6375" },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)

View File

@ -36,6 +36,18 @@
#define SM6350_MSS 4
#define SM6350_MX 5
/* SM6350 Power Domain Indexes */
#define SM6375_VDDCX 0
#define SM6375_VDDCX_AO 1
#define SM6375_VDDCX_VFL 2
#define SM6375_VDDMX 3
#define SM6375_VDDMX_AO 4
#define SM6375_VDDMX_VFL 5
#define SM6375_VDDGX 6
#define SM6375_VDDGX_AO 7
#define SM6375_VDD_LPI_CX 8
#define SM6375_VDD_LPI_MX 9
/* SM8150 Power Domain Indexes */
#define SM8150_MSS 0
#define SM8150_EBI 1

View File

@ -78,11 +78,40 @@ struct llcc_edac_reg_data {
u8 ways_shift;
};
struct llcc_edac_reg_offset {
/* LLCC TRP registers */
u32 trp_ecc_error_status0;
u32 trp_ecc_error_status1;
u32 trp_ecc_sb_err_syn0;
u32 trp_ecc_db_err_syn0;
u32 trp_ecc_error_cntr_clear;
u32 trp_interrupt_0_status;
u32 trp_interrupt_0_clear;
u32 trp_interrupt_0_enable;
/* LLCC Common registers */
u32 cmn_status0;
u32 cmn_interrupt_0_enable;
u32 cmn_interrupt_2_enable;
/* LLCC DRP registers */
u32 drp_ecc_error_cfg;
u32 drp_ecc_error_cntr_clear;
u32 drp_interrupt_status;
u32 drp_interrupt_clear;
u32 drp_interrupt_enable;
u32 drp_ecc_error_status0;
u32 drp_ecc_error_status1;
u32 drp_ecc_sb_err_syn0;
u32 drp_ecc_db_err_syn0;
};
/**
* struct llcc_drv_data - Data associated with the llcc driver
* @regmap: regmap associated with the llcc device
* @bcast_regmap: regmap associated with llcc broadcast offset
* @cfg: pointer to the data structure for slice configuration
* @edac_reg_offset: Offset of the LLCC EDAC registers
* @lock: mutex associated with each slice
* @cfg_size: size of the config data table
* @max_slices: max slices as read from device tree
@ -96,6 +125,7 @@ struct llcc_drv_data {
struct regmap *regmap;
struct regmap *bcast_regmap;
const struct llcc_slice_config *cfg;
const struct llcc_edac_reg_offset *edac_reg_offset;
struct mutex lock;
u32 cfg_size;
u32 max_slices;

View File

@ -75,7 +75,7 @@ struct qmi_elem_info {
enum qmi_array_type array_type;
u8 tlv_type;
u32 offset;
struct qmi_elem_info *ei_array;
const struct qmi_elem_info *ei_array;
};
#define QMI_RESULT_SUCCESS_V01 0
@ -102,7 +102,7 @@ struct qmi_response_type_v01 {
u16 error;
};
extern struct qmi_elem_info qmi_response_type_v01_ei[];
extern const struct qmi_elem_info qmi_response_type_v01_ei[];
/**
* struct qmi_service - context to track lookup-results
@ -173,7 +173,7 @@ struct qmi_txn {
struct completion completion;
int result;
struct qmi_elem_info *ei;
const struct qmi_elem_info *ei;
void *dest;
};
@ -189,7 +189,7 @@ struct qmi_msg_handler {
unsigned int type;
unsigned int msg_id;
struct qmi_elem_info *ei;
const struct qmi_elem_info *ei;
size_t decoded_size;
void (*fn)(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
@ -249,23 +249,23 @@ void qmi_handle_release(struct qmi_handle *qmi);
ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
struct qmi_txn *txn, int msg_id, size_t len,
struct qmi_elem_info *ei, const void *c_struct);
const struct qmi_elem_info *ei, const void *c_struct);
ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
struct qmi_txn *txn, int msg_id, size_t len,
struct qmi_elem_info *ei, const void *c_struct);
const struct qmi_elem_info *ei, const void *c_struct);
ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
int msg_id, size_t len, struct qmi_elem_info *ei,
int msg_id, size_t len, const struct qmi_elem_info *ei,
const void *c_struct);
void *qmi_encode_message(int type, unsigned int msg_id, size_t *len,
unsigned int txn_id, struct qmi_elem_info *ei,
unsigned int txn_id, const struct qmi_elem_info *ei,
const void *c_struct);
int qmi_decode_message(const void *buf, size_t len,
struct qmi_elem_info *ei, void *c_struct);
const struct qmi_elem_info *ei, void *c_struct);
int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
struct qmi_elem_info *ei, void *c_struct);
const struct qmi_elem_info *ei, void *c_struct);
int qmi_txn_wait(struct qmi_txn *txn, unsigned long timeout);
void qmi_txn_cancel(struct qmi_txn *txn);

View File

@ -42,7 +42,7 @@ struct test_name_type_v01 {
char name[TEST_MAX_NAME_SIZE_V01];
};
static struct qmi_elem_info test_name_type_v01_ei[] = {
static const struct qmi_elem_info test_name_type_v01_ei[] = {
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
@ -71,7 +71,7 @@ struct test_ping_req_msg_v01 {
struct test_name_type_v01 client_name;
};
static struct qmi_elem_info test_ping_req_msg_v01_ei[] = {
static const struct qmi_elem_info test_ping_req_msg_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 4,
@ -113,7 +113,7 @@ struct test_ping_resp_msg_v01 {
struct test_name_type_v01 service_name;
};
static struct qmi_elem_info test_ping_resp_msg_v01_ei[] = {
static const struct qmi_elem_info test_ping_resp_msg_v01_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
@ -172,7 +172,7 @@ struct test_data_req_msg_v01 {
struct test_name_type_v01 client_name;
};
static struct qmi_elem_info test_data_req_msg_v01_ei[] = {
static const struct qmi_elem_info test_data_req_msg_v01_ei[] = {
{
.data_type = QMI_DATA_LEN,
.elem_len = 1,
@ -224,7 +224,7 @@ struct test_data_resp_msg_v01 {
struct test_name_type_v01 service_name;
};
static struct qmi_elem_info test_data_resp_msg_v01_ei[] = {
static const struct qmi_elem_info test_data_resp_msg_v01_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,