Commit 66b55cae authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'qcom-drivers-for-6.2' of...

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

Qualcomm driver updates for 6.2

The qcom,msm-id and qcom,board-id DeviceTree properties are documented,
to allow them to be used in configurations or devices requiring these
and the socinfo driver is updated to reuse the introduced identifiers.

The rpmh-rsc driver is extended to register for PM runtime notifications
from the CPU clusters, in order to submit sleep and wake votes the last
core in a cluster is being powered down.

A mechanism for keeping rpmhpd resources voted until sync_state is
introduced, this ensures that power-domains required during boot are
kept enabled. The rpmhpd power-domains for SDM670 are also added.

Support for the new QDU1000/QRU1000 platform is introduced in the rpmhpd
and socinfo drivers.

The APR driver gains missing error handling. QMI message descriptors in
the PDR driver are made const.

Support for the RPM found in SM6375 is added. The SPM driver gains
support for MSM8939 and MSM8976 platforms.

The stats and command-db drvers are marked as not having PM support.

* tag 'qcom-drivers-for-6.2' of https://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (36 commits)
  dt-bindings: firmware: scm: add sdm670 compatible
  soc: qcom: rpmh-rsc: Write CONTROL_TCS with next timer wakeup
  soc: qcom: rpmh-rsc: Save base address of drv
  PM: domains: Store the next hrtimer wakeup in genpd
  soc: qcom: rpmh-rsc: Attach RSC to cluster PM domain
  dt-bindings: soc: qcom: Update devicetree binding document for rpmh-rsc
  dt-bindings: soc: qcom: qcom,smd-rpm: Use qcom,smd-channels on MSM8976
  soc: qcom: apr: Add check for idr_alloc and of_property_read_string_index
  soc: qcom: socinfo: Add QDU1000/QRU1000 SoC IDs to the soc_id table
  dt-bindings: arm: qcom,ids: Add SoC IDs for QDU1000/QRU1000
  soc: qcom: rpmhpd: Add QDU1000/QRU1000 power domains
  dt-bindings: power: rpmpd: Add QDU1000/QRU1000 to rpmpd binding
  dt-bindings: qcom: smp2p: Add WPSS node names to pattern property
  soc: qcom: spm: Implement support for SAWv2.3, MSM8976 L2 PM
  dt-bindings: soc: qcom: spm: Add compatibles for MSM8976 L2
  soc: qcom: llcc: make irq truly optional
  soc: qcom: spm: Add MSM8939 SPM register data
  dt-bindings: soc: qcom: spm: Add MSM8939 CPU compatible
  dt-bindings: soc: qcom: aoss: Add sc8280xp compatible
  dt-bindings: firmware: document Qualcomm SM6375 SCM
  ...

Link: https://lore.kernel.org/r/20221122202748.1854487-1-andersson@kernel.orgSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 919977b6 aa9f4740
......@@ -739,6 +739,126 @@ properties:
- sony,pdx223
- const: qcom,sm8450
# Board compatibles go above
qcom,msm-id:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
minItems: 1
maxItems: 8
items:
items:
- description: |
MSM chipset ID - an exact match value consisting of two bitfields::
- bits 0-15 - The unique MSM chipset ID
- bits 16-31 - Reserved; should be 0
- description: |
Hardware revision ID - a chipset specific 32-bit ID representing
the version of the chipset. It is best a match value - the
bootloader will look for the closest possible match.
deprecated: true
description:
The MSM chipset and hardware revision used Qualcomm bootloaders. It
can optionally be an array of these to indicate multiple hardware that
use the same device tree. It is expected that the bootloader will use
this information at boot-up to decide which device tree to use when given
multiple device trees, some of which may not be compatible with the
actual hardware. It is the bootloader's responsibility to pass the
correct device tree to the kernel.
The property is deprecated.
qcom,board-id:
$ref: /schemas/types.yaml#/definitions/uint32-matrix
minItems: 1
maxItems: 8
oneOf:
- items:
- items:
- description: |
Board ID consisting of three bitfields::
- bits 31-24 - Unused
- bits 23-16 - Platform Version Major
- bits 15-8 - Platform Version Minor
- bits 7-0 - Platform Type
Platform Type field is an exact match value. The
Platform Major/Minor field is a best match. The bootloader will
look for the closest possible match.
- description: |
Subtype ID unique to a Platform Type/Chipset ID. For a given
Platform Type, there will typically only be a single board and the
subtype_id will be 0. However in some cases board variants may
need to be distinguished by different subtype_id values.
- items:
# OnePlus uses a variant of board-id with four elements:
- items:
- const: 8
- const: 0
- description: OnePlus board ID
- description: OnePlus subtype ID
deprecated: true
description:
The board type and revision information. It can optionally be an array
of these to indicate multiple boards that use the same device tree. It
is expected that the bootloader will use this information at boot-up to
decide which device tree to use when given multiple device trees, some of
which may not be compatible with the actual hardware. It is the
bootloader's responsibility to pass the correct device tree to the
kernel
The property is deprecated.
allOf:
# Explicit allow-list for older SoCs. The legacy properties are not allowed
# on newer SoCs.
- if:
properties:
compatible:
contains:
enum:
- qcom,apq8026
- qcom,apq8094
- qcom,apq8096
- qcom,msm8992
- qcom,msm8994
- qcom,msm8996
- qcom,msm8998
- qcom,sdm630
- qcom,sdm632
- qcom,sdm845
- qcom,sdx55
- qcom,sdx65
- qcom,sm6125
- qcom,sm6350
- qcom,sm7225
- qcom,sm8150
- qcom,sm8250
then:
properties:
qcom,board-id: true
qcom,msm-id: true
else:
properties:
qcom,board-id: false
qcom,msm-id: false
- if:
properties:
compatible:
contains:
enum:
- oneplus,cheeseburger
- oneplus,dumpling
- oneplus,enchilada
- oneplus,fajita
then:
properties:
qcom,board-id:
items:
minItems: 4
else:
properties:
qcom,board-id:
items:
maxItems: 2
additionalProperties: true
...
......@@ -41,12 +41,14 @@ properties:
- qcom,scm-sc7180
- qcom,scm-sc7280
- qcom,scm-sc8280xp
- qcom,scm-sdm670
- qcom,scm-sdm845
- qcom,scm-sdx55
- qcom,scm-sdx65
- qcom,scm-sm6115
- qcom,scm-sm6125
- qcom,scm-sm6350
- qcom,scm-sm6375
- qcom,scm-sm8150
- qcom,scm-sm8250
- qcom,scm-sm8350
......@@ -88,6 +90,7 @@ allOf:
- qcom,scm-apq8064
- qcom,scm-msm8660
- qcom,scm-msm8960
- qcom,scm-sm6375
then:
properties:
clock-names:
......
......@@ -28,12 +28,14 @@ properties:
- qcom,msm8998-rpmpd
- qcom,qcm2290-rpmpd
- qcom,qcs404-rpmpd
- qcom,qdu1000-rpmhpd
- qcom,sa8540p-rpmhpd
- qcom,sdm660-rpmpd
- qcom,sc7180-rpmhpd
- qcom,sc7280-rpmhpd
- qcom,sc8180x-rpmhpd
- qcom,sc8280xp-rpmhpd
- qcom,sdm670-rpmhpd
- qcom,sdm845-rpmhpd
- qcom,sdx55-rpmhpd
- qcom,sdx65-rpmhpd
......
......@@ -28,6 +28,7 @@ properties:
- qcom,sc7180-aoss-qmp
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp
- qcom,sc8280xp-aoss-qmp
- qcom,sdm845-aoss-qmp
- qcom,sm6350-aoss-qmp
- qcom,sm8150-aoss-qmp
......
......@@ -99,6 +99,9 @@ properties:
- const: drv-2
- const: drv-3
power-domains:
maxItems: 1
bcm-voter:
$ref: /schemas/interconnect/qcom,bcm-voter.yaml#
......@@ -151,6 +154,7 @@ examples:
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
power-domains = <&CLUSTER_PD>;
};
- |
......@@ -197,6 +201,7 @@ examples:
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 0>;
power-domains = <&CLUSTER_PD>;
clock-controller {
compatible = "qcom,sm8350-rpmh-clk";
......
......@@ -4,7 +4,7 @@
$id: "http://devicetree.org/schemas/soc/qcom/qcom,smd-rpm.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Qualcomm Resource Power Manager (RPM) over SMD
title: Qualcomm Resource Power Manager (RPM) over SMD/GLINK
description: |
This driver is used to interface with the Resource Power Manager (RPM) found
......@@ -12,9 +12,9 @@ description: |
to vote for state of the system resources, such as clocks, regulators and bus
frequencies.
The SMD information for the RPM edge should be filled out. See qcom,smd.yaml
for the required edge properties. All SMD related properties will reside
within the RPM node itself.
The SMD or GLINK information for the RPM edge should be filled out. See
qcom,smd.yaml for the required edge properties. All SMD/GLINK related
properties will reside within the RPM node itself.
The RPM exposes resources to its subnodes. The rpm_requests node must be
present and this subnode may contain children that designate regulator
......@@ -45,6 +45,7 @@ properties:
- qcom,rpm-sdm660
- qcom,rpm-sm6115
- qcom,rpm-sm6125
- qcom,rpm-sm6375
- qcom,rpm-qcm2290
- qcom,rpm-qcs404
......@@ -55,12 +56,23 @@ properties:
power-controller:
$ref: /schemas/power/qcom,rpmpd.yaml#
qcom,glink-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the RPM communication
items:
- const: rpm_requests
qcom,smd-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the RPM communication
items:
- const: rpm_requests
patternProperties:
"^regulators(-[01])?$":
$ref: /schemas/regulator/qcom,smd-rpm-regulator.yaml#
unevaluatedProperties: false
if:
properties:
compatible:
......@@ -69,10 +81,18 @@ if:
- qcom,rpm-apq8084
- qcom,rpm-msm8916
- qcom,rpm-msm8974
- qcom,rpm-msm8976
- qcom,rpm-msm8953
then:
properties:
qcom,glink-channels: false
required:
- qcom,smd-channels
else:
properties:
qcom,smd-channels: false
required:
- qcom,glink-channels
required:
- compatible
......
......@@ -60,7 +60,7 @@ properties:
Two identifiers of the inbound and outbound smem items used for this edge.
patternProperties:
"^master-kernel|slave-kernel|ipa-ap-to-modem|ipa-modem-to-ap$":
"^master-kernel|slave-kernel|ipa-ap-to-modem|ipa-modem-to-ap|wlan-ap-to-wpss|wlan-wpss-to-ap$":
type: object
description:
Each SMP2P pair contain a set of inbound and outbound entries, these are
......
......@@ -24,8 +24,11 @@ properties:
- qcom,msm8998-silver-saw2-v4.1-l2
- qcom,msm8909-saw2-v3.0-cpu
- qcom,msm8916-saw2-v3.0-cpu
- qcom,msm8939-saw2-v3.0-cpu
- qcom,msm8226-saw2-v2.1-cpu
- qcom,msm8974-saw2-v2.1-cpu
- qcom,msm8976-gold-saw2-v2.3-l2
- qcom,msm8976-silver-saw2-v2.3-l2
- qcom,apq8084-saw2-v2.1-cpu
- qcom,apq8064-saw2-v1.1-cpu
- const: qcom,saw2
......
......@@ -494,6 +494,31 @@ void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next)
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_set_next_wakeup);
/**
* dev_pm_genpd_get_next_hrtimer - Return the next_hrtimer for the genpd
* @dev: A device that is attached to the genpd.
*
* This routine should typically be called for a device, at the point of when a
* GENPD_NOTIFY_PRE_OFF notification has been sent for it.
*
* Returns the aggregated value of the genpd's next hrtimer or KTIME_MAX if no
* valid value have been set.
*/
ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev)
{
struct generic_pm_domain *genpd;
genpd = dev_to_genpd_safe(dev);
if (!genpd)
return KTIME_MAX;
if (genpd->gd)
return genpd->gd->next_hrtimer;
return KTIME_MAX;
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_get_next_hrtimer);
static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
{
unsigned int state_idx = genpd->state_idx;
......@@ -1994,6 +2019,7 @@ static int genpd_alloc_data(struct generic_pm_domain *genpd)
gd->max_off_time_ns = -1;
gd->max_off_time_changed = true;
gd->next_wakeup = KTIME_MAX;
gd->next_hrtimer = KTIME_MAX;
}
/* Use only one "off" state if there were no states declared */
......
......@@ -375,6 +375,9 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
if (idle_duration_ns <= 0)
return false;
/* Store the next domain_wakeup to allow consumers to use it. */
genpd->gd->next_hrtimer = domain_wakeup;
/*
* Find the deepest idle state that has its residency value satisfied
* and by also taking into account the power off latency for the state.
......
......@@ -454,11 +454,19 @@ static int apr_add_device(struct device *dev, struct device_node *np,
adev->dev.driver = NULL;
spin_lock(&apr->svcs_lock);
idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC);
ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC);
spin_unlock(&apr->svcs_lock);
if (ret < 0) {
dev_err(dev, "idr_alloc failed: %d\n", ret);
goto out;
}
of_property_read_string_index(np, "qcom,protection-domain",
1, &adev->service_path);
ret = of_property_read_string_index(np, "qcom,protection-domain",
1, &adev->service_path);
if (ret < 0) {
dev_err(dev, "Failed to read second value of qcom,protection-domain\n");
goto out;
}
dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev));
......@@ -468,6 +476,7 @@ static int apr_add_device(struct device *dev, struct device_node *np,
put_device(&adev->dev);
}
out:
return ret;
}
......
......@@ -338,6 +338,8 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
debugfs_create_file("cmd-db", 0400, NULL, NULL, &cmd_db_debugfs_ops);
device_set_pm_not_required(&pdev->dev);
return 0;
}
......
......@@ -849,7 +849,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
if (ret)
goto err;
drv_data->ecc_irq = platform_get_irq(pdev, 0);
drv_data->ecc_irq = platform_get_irq_optional(pdev, 0);
if (drv_data->ecc_irq >= 0) {
llcc_edac = platform_device_register_data(&pdev->dev,
"qcom_llcc_edac", -1, drv_data,
......
......@@ -28,7 +28,7 @@ struct servreg_location_entry {
u32 instance;
};
static struct qmi_elem_info servreg_location_entry_ei[] = {
static const struct qmi_elem_info servreg_location_entry_ei[] = {
{
.data_type = QMI_STRING,
.elem_len = SERVREG_NAME_LENGTH + 1,
......@@ -74,7 +74,7 @@ struct servreg_get_domain_list_req {
u32 domain_offset;
};
static struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
static const struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
{
.data_type = QMI_STRING,
.elem_len = SERVREG_NAME_LENGTH + 1,
......@@ -116,7 +116,7 @@ struct servreg_get_domain_list_resp {
struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
};
static struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
static const struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
......@@ -199,7 +199,7 @@ struct servreg_register_listener_req {
char service_path[SERVREG_NAME_LENGTH + 1];
};
static struct qmi_elem_info servreg_register_listener_req_ei[] = {
static const struct qmi_elem_info servreg_register_listener_req_ei[] = {
{
.data_type = QMI_UNSIGNED_1_BYTE,
.elem_len = 1,
......@@ -227,7 +227,7 @@ struct servreg_register_listener_resp {
enum servreg_service_state curr_state;
};
static struct qmi_elem_info servreg_register_listener_resp_ei[] = {
static const struct qmi_elem_info servreg_register_listener_resp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
......@@ -263,7 +263,7 @@ struct servreg_restart_pd_req {
char service_path[SERVREG_NAME_LENGTH + 1];
};
static struct qmi_elem_info servreg_restart_pd_req_ei[] = {
static const struct qmi_elem_info servreg_restart_pd_req_ei[] = {
{
.data_type = QMI_STRING,
.elem_len = SERVREG_NAME_LENGTH + 1,
......@@ -280,7 +280,7 @@ struct servreg_restart_pd_resp {
struct qmi_response_type_v01 resp;
};
static struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
static const struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
......@@ -300,7 +300,7 @@ struct servreg_state_updated_ind {
u16 transaction_id;
};
static struct qmi_elem_info servreg_state_updated_ind_ei[] = {
static const struct qmi_elem_info servreg_state_updated_ind_ei[] = {
{
.data_type = QMI_SIGNED_4_BYTE_ENUM,
.elem_len = 1,
......@@ -336,7 +336,7 @@ struct servreg_set_ack_req {
u16 transaction_id;
};
static struct qmi_elem_info servreg_set_ack_req_ei[] = {
static const struct qmi_elem_info servreg_set_ack_req_ei[] = {
{
.data_type = QMI_STRING,
.elem_len = SERVREG_NAME_LENGTH + 1,
......@@ -362,7 +362,7 @@ struct servreg_set_ack_resp {
struct qmi_response_type_v01 resp;
};
static struct qmi_elem_info servreg_set_ack_resp_ei[] = {
static const struct qmi_elem_info servreg_set_ack_resp_ei[] = {
{
.data_type = QMI_STRUCT,
.elem_len = 1,
......
......@@ -217,6 +217,8 @@ static int qcom_stats_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, root);
device_set_pm_not_required(&pdev->dev);
return 0;
}
......
......@@ -91,13 +91,15 @@ struct rpmh_ctrlr {
* Resource State Coordinator controller (RSC)
*
* @name: Controller identifier.
* @base: Start address of the DRV registers in this controller.
* @tcs_base: Start address of the TCS registers in this controller.
* @id: Instance id in the controller (Direct Resource Voter).
* @num_tcs: Number of TCSes in this DRV.
* @rsc_pm: CPU PM notifier for controller.
* Used when solver mode is not present.
* @cpus_in_pm: Number of CPUs not in idle power collapse.
* Used when solver mode is not present.
* Used when solver mode and "power-domains" is not present.
* @genpd_nb: PM Domain notifier for cluster genpd notifications.
* @tcs: TCS groups.
* @tcs_in_use: S/W state of the TCS; only set for ACTIVE_ONLY
* transfers, but might show a sleep/wake TCS in use if
......@@ -110,25 +112,30 @@ struct rpmh_ctrlr {
* @tcs_wait: Wait queue used to wait for @tcs_in_use to free up a
* slot
* @client: Handle to the DRV's client.
* @dev: RSC device.
*/
struct rsc_drv {
const char *name;
void __iomem *base;
void __iomem *tcs_base;
int id;
int num_tcs;
struct notifier_block rsc_pm;
struct notifier_block genpd_nb;
atomic_t cpus_in_pm;
struct tcs_group tcs[TCS_TYPE_NR];
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
spinlock_t lock;
wait_queue_head_t tcs_wait;
struct rpmh_ctrlr client;
struct device *dev;
};
int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg);
int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
const struct tcs_request *msg);
void rpmh_rsc_invalidate(struct rsc_drv *drv);
void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv);
void rpmh_tx_done(const struct tcs_request *msg, int r);
int rpmh_flush(struct rpmh_ctrlr *ctrlr);
......
......@@ -12,16 +12,21 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
#include <clocksource/arm_arch_timer.h>
#include <soc/qcom/cmd-db.h>
#include <soc/qcom/tcs.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
......@@ -46,6 +51,14 @@
#define DRV_NCPT_MASK 0x1F
#define DRV_NCPT_SHIFT 27
/* Offsets for CONTROL TCS Registers */
#define RSC_DRV_CTL_TCS_DATA_HI 0x38
#define RSC_DRV_CTL_TCS_DATA_HI_MASK 0xFFFFFF
#define RSC_DRV_CTL_TCS_DATA_HI_VALID BIT(31)
#define RSC_DRV_CTL_TCS_DATA_LO 0x40
#define RSC_DRV_CTL_TCS_DATA_LO_MASK 0xFFFFFFFF
#define RSC_DRV_CTL_TCS_DATA_SIZE 32
/* Offsets for common TCS Registers, one bit per TCS */
#define RSC_DRV_IRQ_ENABLE 0x00
#define RSC_DRV_IRQ_STATUS 0x04
......@@ -139,6 +152,14 @@
* +---------------------------------------------------+
*/
#define USECS_TO_CYCLES(time_usecs) \
xloops_to_cycles((time_usecs) * 0x10C7UL)
static inline unsigned long xloops_to_cycles(u64 xloops)
{
return (xloops * loops_per_jiffy * HZ) >> 32;
}
static inline void __iomem *
tcs_reg_addr(const struct rsc_drv *drv, int reg, int tcs_id)
{
......@@ -753,6 +774,48 @@ static bool rpmh_rsc_ctrlr_is_busy(struct rsc_drv *drv)
return set < max;
}
/**
* rpmh_rsc_write_next_wakeup() - Write next wakeup in CONTROL_TCS.
* @drv: The controller
*
* Writes maximum wakeup cycles when called from suspend.
* Writes earliest hrtimer wakeup when called from idle.
*/
void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv)
{
ktime_t now, wakeup;
u64 wakeup_us, wakeup_cycles = ~0;
u32 lo, hi;
if (!drv->tcs[CONTROL_TCS].num_tcs || !drv->genpd_nb.notifier_call)
return;
/* Set highest time when system (timekeeping) is suspended */
if (system_state == SYSTEM_SUSPEND)
goto exit;
/* Find the earliest hrtimer wakeup from online cpus */
wakeup = dev_pm_genpd_get_next_hrtimer(drv->dev);
/* Find the relative wakeup in kernel time scale */
now = ktime_get();
wakeup = ktime_sub(wakeup, now);
wakeup_us = ktime_to_us(wakeup);
/* Convert the wakeup to arch timer scale */
wakeup_cycles = USECS_TO_CYCLES(wakeup_us);
wakeup_cycles += arch_timer_read_counter();
exit:
lo = wakeup_cycles & RSC_DRV_CTL_TCS_DATA_LO_MASK;
hi = wakeup_cycles >> RSC_DRV_CTL_TCS_DATA_SIZE;
hi &= RSC_DRV_CTL_TCS_DATA_HI_MASK;
hi |= RSC_DRV_CTL_TCS_DATA_HI_VALID;
writel_relaxed(lo, drv->base + RSC_DRV_CTL_TCS_DATA_LO);
writel_relaxed(hi, drv->base + RSC_DRV_CTL_TCS_DATA_HI);
}
/**
* rpmh_rsc_cpu_pm_callback() - Check if any of the AMCs are busy.
* @nfb: Pointer to the notifier block in struct rsc_drv.
......@@ -834,8 +897,51 @@ static int rpmh_rsc_cpu_pm_callback(struct notifier_block *nfb,
return ret;
}
static int rpmh_probe_tcs_config(struct platform_device *pdev,
struct rsc_drv *drv, void __iomem *base)
/**
* rpmh_rsc_pd_callback() - Check if any of the AMCs are busy.
* @nfb: Pointer to the genpd notifier block in struct rsc_drv.
* @action: GENPD_NOTIFY_PRE_OFF, GENPD_NOTIFY_OFF, GENPD_NOTIFY_PRE_ON or GENPD_NOTIFY_ON.
* @v: Unused
*
* This function is given to dev_pm_genpd_add_notifier() so we can be informed
* about when cluster-pd is going down. When cluster go down we know no more active
* transfers will be started so we write sleep/wake sets. This function gets
* called from cpuidle code paths and also at system suspend time.
*
* If AMCs are not busy then writes cached sleep and wake messages to TCSes.
* The firmware then takes care of triggering them when entering deepest low power modes.
*
* Return:
* * NOTIFY_OK - success
* * NOTIFY_BAD - failure
*/
static int rpmh_rsc_pd_callback(struct notifier_block *nfb,
unsigned long action, void *v)
{
struct rsc_drv *drv = container_of(nfb, struct rsc_drv, genpd_nb);
/* We don't need to lock as genpd on/off are serialized */
if ((action == GENPD_NOTIFY_PRE_OFF) &&
(rpmh_rsc_ctrlr_is_busy(drv) || rpmh_flush(&drv->client)))
return NOTIFY_BAD;
return NOTIFY_OK;
}
static int rpmh_rsc_pd_attach(struct rsc_drv *drv, struct device *dev)
{
int ret;
pm_runtime_enable(dev);
drv->genpd_nb.notifier_call = rpmh_rsc_pd_callback;
ret = dev_pm_genpd_add_notifier(dev, &drv->genpd_nb);
if (ret)
pm_runtime_disable(dev);
return ret;
}
static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv *drv)
{
struct tcs_type_config {
u32 type;
......@@ -849,9 +955,9 @@ static int rpmh_probe_tcs_config(struct platform_device *pdev,
ret = of_property_read_u32(dn, "qcom,tcs-offset", &offset);
if (ret)
return ret;
drv->tcs_base = base + offset;
drv->tcs_base = drv->base + offset;
config = readl_relaxed(base + DRV_PRNT_CHLD_CONFIG);
config = readl_relaxed(drv->base + DRV_PRNT_CHLD_CONFIG);
max_tcs = config;
max_tcs &= DRV_NUM_TCS_MASK << (DRV_NUM_TCS_SHIFT * drv->id);
......@@ -913,7 +1019,6 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
char drv_id[10] = {0};
int ret, irq;
u32 solver_config;
void __iomem *base;
/*
* Even though RPMh doesn't directly use cmd-db, all of its children
......@@ -940,11 +1045,11 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
drv->name = dev_name(&pdev->dev);
snprintf(drv_id, ARRAY_SIZE(drv_id), "drv-%d", drv->id);
base = devm_platform_ioremap_resource_byname(pdev, drv_id);
if (IS_ERR(base))
return PTR_ERR(base);
drv->base = devm_platform_ioremap_resource_byname(pdev, drv_id);
if (IS_ERR(drv->base))
return PTR_ERR(drv->base);
ret = rpmh_probe_tcs_config(pdev, drv, base);
ret = rpmh_probe_tcs_config(pdev, drv);
if (ret)
return ret;
......@@ -963,16 +1068,22 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
return ret;
/*
* CPU PM notification are not required for controllers that support
* CPU PM/genpd notification are not required for controllers that support
* 'HW solver' mode where they can be in autonomous mode executing low
* power mode to power down.
*/
solver_config = readl_relaxed(base + DRV_SOLVER_CONFIG);
solver_config = readl_relaxed(drv->base + DRV_SOLVER_CONFIG);
solver_config &= DRV_HW_SOLVER_MASK << DRV_HW_SOLVER_SHIFT;
solver_config = solver_config >> DRV_HW_SOLVER_SHIFT;
if (!solver_config) {
drv->rsc_pm.notifier_call = rpmh_rsc_cpu_pm_callback;
cpu_pm_register_notifier(&drv->rsc_pm);
if (pdev->dev.pm_domain) {
ret = rpmh_rsc_pd_attach(drv, &pdev->dev);
if (ret)
return ret;
} else {
drv->rsc_pm.notifier_call = rpmh_rsc_cpu_pm_callback;
cpu_pm_register_notifier(&drv->rsc_pm);
}
}
/* Enable the active TCS to send requests immediately */
......@@ -984,8 +1095,15 @@ static int rpmh_rsc_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&drv->client.batch_cache);
dev_set_drvdata(&pdev->dev, drv);
drv->dev = &pdev->dev;
return devm_of_platform_populate(&pdev->dev);
ret = devm_of_platform_populate(&pdev->dev);
if (ret && pdev->dev.pm_domain) {
dev_pm_genpd_remove_notifier(&pdev->dev);
pm_runtime_disable(&pdev->dev);
}
return ret;
}
static const struct of_device_id rpmh_drv_match[] = {
......
......@@ -450,7 +450,7 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr)
if (!ctrlr->dirty) {
pr_debug("Skipping flush, TCS has latest data.\n");
goto exit;
goto write_next_wakeup;
}
/* Invalidate the TCSes first to avoid stale data */
......@@ -479,6 +479,8 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr)
ctrlr->dirty = false;
write_next_wakeup:
rpmh_rsc_write_next_wakeup(ctrlr_to_drv(ctrlr));
exit:
spin_unlock(&ctrlr->cache_lock);
return ret;
......
......@@ -39,6 +39,7 @@
* @res_name: Resource name used for cmd-db lookup
* @addr: Resource address as looped up using resource name from
* cmd-db
* @state_synced: Indicator that sync_state has been invoked for the rpmhpd resource
*/
struct rpmhpd {
struct device *dev;
......@@ -54,6 +55,7 @@ struct rpmhpd {
bool enabled;
const char *res_name;
u32 addr;
bool state_synced;
};
struct rpmhpd_desc {
......@@ -210,6 +212,23 @@ static const struct rpmhpd_desc sa8540p_desc = {
.num_pds = ARRAY_SIZE(sa8540p_rpmhpds),
};
/* SDM670 RPMH powerdomains */
static struct rpmhpd *sdm670_rpmhpds[] = {
[SDM670_CX] = &cx_w_mx_parent,
[SDM670_CX_AO] = &cx_ao_w_mx_parent,
[SDM670_GFX] = &gfx,
[SDM670_LCX] = &lcx,
[SDM670_LMX] = &lmx,
[SDM670_MSS] = &mss,
[SDM670_MX] = &mx,
[SDM670_MX_AO] = &mx_ao,
};
static const struct rpmhpd_desc sdm670_desc = {
.rpmhpds = sdm670_rpmhpds,
.num_pds = ARRAY_SIZE(sdm670_rpmhpds),
};
/* SDM845 RPMH powerdomains */
static struct rpmhpd *sdm845_rpmhpds[] = {
[SDM845_CX] = &cx_w_mx_parent,
......@@ -353,6 +372,19 @@ static const struct rpmhpd_desc sm8450_desc = {
.num_pds = ARRAY_SIZE(sm8450_rpmhpds),
};
/* QDU1000/QRU1000 RPMH powerdomains */
static struct rpmhpd *qdu1000_rpmhpds[] = {
[QDU1000_CX] = &cx,
[QDU1000_EBI] = &ebi,
[QDU1000_MSS] = &mss,
[QDU1000_MX] = &mx,
};
static const struct rpmhpd_desc qdu1000_desc = {
.rpmhpds = qdu1000_rpmhpds,
.num_pds = ARRAY_SIZE(qdu1000_rpmhpds),
};
/* SC7180 RPMH powerdomains */
static struct rpmhpd *sc7180_rpmhpds[] = {
[SC7180_CX] = &cx_w_mx_parent,
......@@ -430,11 +462,13 @@ static const struct rpmhpd_desc sc8280xp_desc = {
};
static const struct of_device_id rpmhpd_match_table[] = {
{ .compatible = "qcom,qdu1000-rpmhpd", .data = &qdu1000_desc },
{ .compatible = "qcom,sa8540p-rpmhpd", .data = &sa8540p_desc },
{ .compatible = "qcom,sc7180-rpmhpd", .data = &sc7180_desc },
{ .compatible = "qcom,sc7280-rpmhpd", .data = &sc7280_desc },
{ .compatible = "qcom,sc8180x-rpmhpd", .data = &sc8180x_desc },
{ .compatible = "qcom,sc8280xp-rpmhpd", .data = &sc8280xp_desc },
{ .compatible = "qcom,sdm670-rpmhpd", .data = &sdm670_desc },
{ .compatible = "qcom,sdm845-rpmhpd", .data = &sdm845_desc },
{ .compatible = "qcom,sdx55-rpmhpd", .data = &sdx55_desc},
{ .compatible = "qcom,sdx65-rpmhpd", .data = &sdx65_desc},
......@@ -493,7 +527,13 @@ static int rpmhpd_aggregate_corner(struct rpmhpd *pd, unsigned int corner)
unsigned int this_active_corner = 0, this_sleep_corner = 0;
unsigned int peer_active_corner = 0, peer_sleep_corner = 0;
to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
if (pd->state_synced) {
to_active_sleep(pd, corner, &this_active_corner, &this_sleep_corner);
} else {
/* Clamp to highest corner if sync_state hasn't happened */
this_active_corner = pd->level_count - 1;
this_sleep_corner = pd->level_count - 1;
}
if (peer && peer->enabled)
to_active_sleep(peer, peer->corner, &peer_active_corner,
......@@ -708,11 +748,40 @@ static int rpmhpd_probe(struct platform_device *pdev)
return of_genpd_add_provider_onecell(pdev->dev.of_node, data);
}
static void rpmhpd_sync_state(struct device *dev)
{
const struct rpmhpd_desc *desc = of_device_get_match_data(dev);
struct rpmhpd **rpmhpds = desc->rpmhpds;
unsigned int corner;
struct rpmhpd *pd;
unsigned int i;
int ret;
mutex_lock(&rpmhpd_lock);
for (i = 0; i < desc->num_pds; i++) {
pd = rpmhpds[i];
if (!pd)
continue;
pd->state_synced = true;
if (pd->enabled)
corner = max(pd->corner, pd->enable_corner);
else
corner = 0;
ret = rpmhpd_aggregate_corner(pd, corner);
if (ret)
dev_err(dev, "failed to sync %s\n", pd->res_name);
}
mutex_unlock(&rpmhpd_lock);
}
static struct platform_driver rpmhpd_driver = {
.driver = {
.name = "qcom-rpmhpd",
.of_match_table = rpmhpd_match_table,
.suppress_bind_attrs = true,
.sync_state = rpmhpd_sync_state,
},
.probe = rpmhpd_probe,
};
......
......@@ -75,7 +75,7 @@ struct qcom_rpm_message {
__le32 length;
union {
__le32 msg_id;
u8 message[0];
DECLARE_FLEX_ARRAY(u8, message);
};
};
......@@ -246,6 +246,7 @@ static const struct of_device_id qcom_smd_rpm_of_match[] = {
{ .compatible = "qcom,rpm-sdm660" },
{ .compatible = "qcom,rpm-sm6115" },
{ .compatible = "qcom,rpm-sm6125" },
{ .compatible = "qcom,rpm-sm6375" },
{ .compatible = "qcom,rpm-qcm2290" },
{ .compatible = "qcom,rpm-qcs404" },
{}
......
......@@ -422,7 +422,7 @@ static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p,
char buf[SMP2P_MAX_ENTRY_NAME] = {};
/* Allocate an entry from the smem item */
strlcpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME);
strscpy(buf, entry->name, SMP2P_MAX_ENTRY_NAME);
memcpy(out->entries[out->valid_entries].name, buf, SMP2P_MAX_ENTRY_NAME);
/* Make the logical entry reference the physical value */
......
......@@ -12,11 +12,14 @@
#include <linux/slab.h>
#include <linux/soc/qcom/smem.h>
#include <linux/string.h>
#include <linux/stringify.h>
#include <linux/sys_soc.h>
#include <linux/types.h>
#include <asm/unaligned.h>
#include <dt-bindings/arm/qcom,ids.h>
/*
* SoC version type with major number in the upper 16 bits and minor
* number in the lower 16 bits.
......@@ -25,6 +28,10 @@
#define SOCINFO_MINOR(ver) ((ver) & 0xffff)
#define SOCINFO_VERSION(maj, min) ((((maj) & 0xffff) << 16)|((min) & 0xffff))
/* Helper macros to create soc_id table */
#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
......@@ -207,135 +214,141 @@ struct soc_id {
};
static const struct soc_id soc_id[] = {
{ 87, "MSM8960" },
{ 109, "APQ8064" },
{ 122, "MSM8660A" },
{ 123, "MSM8260A" },
{ 124, "APQ8060A" },
{ 126, "MSM8974" },
{ 130, "MPQ8064" },
{ 138, "MSM8960AB" },
{ 139, "APQ8060AB" },
{ 140, "MSM8260AB" },
{ 141, "MSM8660AB" },
{ 145, "MSM8626" },
{ 147, "MSM8610" },
{ 153, "APQ8064AB" },
{ 158, "MSM8226" },
{ 159, "MSM8526" },
{ 161, "MSM8110" },
{ 162, "MSM8210" },
{ 163, "MSM8810" },
{ 164, "MSM8212" },
{ 165, "MSM8612" },
{ 166, "MSM8112" },
{ 168, "MSM8225Q" },
{ 169, "MSM8625Q" },
{ 170, "MSM8125Q" },
{ 172, "APQ8064AA" },
{ 178, "APQ8084" },
{ 184, "APQ8074" },
{ 185, "MSM8274" },
{ 186, "MSM8674" },
{ 194, "MSM8974PRO-AC" },
{ 198, "MSM8126" },
{ 199, "APQ8026" },
{ 200, "MSM8926" },
{ 205, "MSM8326" },
{ 206, "MSM8916" },
{ 207, "MSM8994" },
{ 208, "APQ8074PRO-AA" },
{ 209, "APQ8074PRO-AB" },
{ 210, "APQ8074PRO-AC" },
{ 211, "MSM8274PRO-AA" },
{ 212, "MSM8274PRO-AB" },
{ 213, "MSM8274PRO-AC" },
{ 214, "MSM8674PRO-AA" },
{ 215, "MSM8674PRO-AB" },
{ 216, "MSM8674PRO-AC" },
{ 217, "MSM8974PRO-AA" },
{ 218, "MSM8974PRO-AB" },
{ 219, "APQ8028" },
{ 220, "MSM8128" },
{ 221, "MSM8228" },
{ 222, "MSM8528" },
{ 223, "MSM8628" },
{ 224, "MSM8928" },
{ 225, "MSM8510" },
{ 226, "MSM8512" },
{ 233, "MSM8936" },
{ 239, "MSM8939" },
{ 240, "APQ8036" },
{ 241, "APQ8039" },
{ 246, "MSM8996" },
{ 247, "APQ8016" },
{ 248, "MSM8216" },
{ 249, "MSM8116" },
{ 250, "MSM8616" },
{ 251, "MSM8992" },
{ 253, "APQ8094" },
{ 290, "MDM9607" },
{ 291, "APQ8096" },
{ 292, "MSM8998" },
{ 293, "MSM8953" },
{ 296, "MDM8207" },
{ 297, "MDM9207" },
{ 298, "MDM9307" },
{ 299, "MDM9628" },
{ 304, "APQ8053" },
{ 305, "MSM8996SG" },
{ 310, "MSM8996AU" },
{ 311, "APQ8096AU" },
{ 312, "APQ8096SG" },
{ 317, "SDM660" },
{ 318, "SDM630" },
{ 319, "APQ8098" },
{ 321, "SDM845" },
{ 322, "MDM9206" },
{ 323, "IPQ8074" },
{ 324, "SDA660" },
{ 325, "SDM658" },
{ 326, "SDA658" },
{ 327, "SDA630" },
{ 338, "SDM450" },
{ 341, "SDA845" },
{ 342, "IPQ8072" },
{ 343, "IPQ8076" },
{ 344, "IPQ8078" },
{ 345, "SDM636" },
{ 346, "SDA636" },
{ 349, "SDM632" },
{ 350, "SDA632" },
{ 351, "SDA450" },
{ 356, "SM8250" },
{ 375, "IPQ8070" },
{ 376, "IPQ8071" },
{ 389, "IPQ8072A" },
{ 390, "IPQ8074A" },
{ 391, "IPQ8076A" },
{ 392, "IPQ8078A" },
{ 394, "SM6125" },
{ 395, "IPQ8070A" },
{ 396, "IPQ8071A" },
{ 402, "IPQ6018" },
{ 403, "IPQ6028" },
{ 421, "IPQ6000" },
{ 422, "IPQ6010" },
{ 425, "SC7180" },
{ 434, "SM6350" },
{ 439, "SM8350" },
{ 449, "SC8280XP" },
{ 453, "IPQ6005" },
{ 455, "QRB5165" },
{ 457, "SM8450" },
{ 459, "SM7225" },
{ 460, "SA8295P" },
{ 461, "SA8540P" },
{ 480, "SM8450" },
{ 482, "SM8450" },
{ 487, "SC7280" },
{ 495, "SC7180P" },
{ 507, "SM6375" },
{ qcom_board_id(MSM8960) },
{ qcom_board_id(APQ8064) },
{ qcom_board_id(MSM8660A) },
{ qcom_board_id(MSM8260A) },
{ qcom_board_id(APQ8060A) },
{ qcom_board_id(MSM8974) },
{ qcom_board_id(MPQ8064) },
{ qcom_board_id(MSM8960AB) },
{ qcom_board_id(APQ8060AB) },
{ qcom_board_id(MSM8260AB) },
{ qcom_board_id(MSM8660AB) },
{ qcom_board_id(MSM8626) },
{ qcom_board_id(MSM8610) },
{ qcom_board_id(APQ8064AB) },
{ qcom_board_id(MSM8226) },
{ qcom_board_id(MSM8526) },
{ qcom_board_id(MSM8110) },
{ qcom_board_id(MSM8210) },
{ qcom_board_id(MSM8810) },
{ qcom_board_id(MSM8212) },
{ qcom_board_id(MSM8612) },
{ qcom_board_id(MSM8112) },
{ qcom_board_id(MSM8225Q) },
{ qcom_board_id(MSM8625Q) },
{ qcom_board_id(MSM8125Q) },
{ qcom_board_id(APQ8064AA) },
{ qcom_board_id(APQ8084) },
{ qcom_board_id(APQ8074) },
{ qcom_board_id(MSM8274) },
{ qcom_board_id(MSM8674) },
{ qcom_board_id_named(MSM8974PRO_AC, "MSM8974PRO-AC") },
{ qcom_board_id(MSM8126) },
{ qcom_board_id(APQ8026) },
{ qcom_board_id(MSM8926) },
{ qcom_board_id(MSM8326) },
{ qcom_board_id(MSM8916) },
{ qcom_board_id(MSM8994) },
{ qcom_board_id_named(APQ8074PRO_AA, "APQ8074PRO-AA") },
{ qcom_board_id_named(APQ8074PRO_AB, "APQ8074PRO-AB") },
{ qcom_board_id_named(APQ8074PRO_AC, "APQ8074PRO-AC") },
{ qcom_board_id_named(MSM8274PRO_AA, "MSM8274PRO-AA") },
{ qcom_board_id_named(MSM8274PRO_AB, "MSM8274PRO-AB") },
{ qcom_board_id_named(MSM8274PRO_AC, "MSM8274PRO-AC") },
{ qcom_board_id_named(MSM8674PRO_AA, "MSM8674PRO-AA") },
{ qcom_board_id_named(MSM8674PRO_AB, "MSM8674PRO-AB") },
{ qcom_board_id_named(MSM8674PRO_AC, "MSM8674PRO-AC") },
{ qcom_board_id_named(MSM8974PRO_AA, "MSM8974PRO-AA") },
{ qcom_board_id_named(MSM8974PRO_AB, "MSM8974PRO-AB") },
{ qcom_board_id(APQ8028) },
{ qcom_board_id(MSM8128) },
{ qcom_board_id(MSM8228) },
{ qcom_board_id(MSM8528) },
{ qcom_board_id(MSM8628) },
{ qcom_board_id(MSM8928) },
{ qcom_board_id(MSM8510) },
{ qcom_board_id(MSM8512) },
{ qcom_board_id(MSM8936) },
{ qcom_board_id(MSM8939) },
{ qcom_board_id(APQ8036) },
{ qcom_board_id(APQ8039) },
{ qcom_board_id(MSM8996) },
{ qcom_board_id(APQ8016) },
{ qcom_board_id(MSM8216) },
{ qcom_board_id(MSM8116) },
{ qcom_board_id(MSM8616) },
{ qcom_board_id(MSM8992) },
{ qcom_board_id(APQ8094) },
{ qcom_board_id(MDM9607) },
{ qcom_board_id(APQ8096) },
{ qcom_board_id(MSM8998) },
{ qcom_board_id(MSM8953) },
{ qcom_board_id(MDM8207) },
{ qcom_board_id(MDM9207) },
{ qcom_board_id(MDM9307) },
{ qcom_board_id(MDM9628) },
{ qcom_board_id(APQ8053) },
{ qcom_board_id(MSM8996SG) },
{ qcom_board_id(MSM8996AU) },
{ qcom_board_id(APQ8096AU) },
{ qcom_board_id(APQ8096SG) },
{ qcom_board_id(SDM660) },
{ qcom_board_id(SDM630) },
{ qcom_board_id(APQ8098) },
{ qcom_board_id(SDM845) },
{ qcom_board_id(MDM9206) },
{ qcom_board_id(IPQ8074) },
{ qcom_board_id(SDA660) },
{ qcom_board_id(SDM658) },
{ qcom_board_id(SDA658) },
{ qcom_board_id(SDA630) },
{ qcom_board_id(SDM450) },
{ qcom_board_id(SDA845) },
{ qcom_board_id(IPQ8072) },
{ qcom_board_id(IPQ8076) },
{ qcom_board_id(IPQ8078) },
{ qcom_board_id(SDM636) },
{ qcom_board_id(SDA636) },
{ qcom_board_id(SDM632) },
{ qcom_board_id(SDA632) },
{ qcom_board_id(SDA450) },
{ qcom_board_id(SM8250) },
{ qcom_board_id(IPQ8070) },
{ qcom_board_id(IPQ8071) },
{ qcom_board_id(IPQ8072A) },
{ qcom_board_id(IPQ8074A) },
{ qcom_board_id(IPQ8076A) },
{ qcom_board_id(IPQ8078A) },
{ qcom_board_id(SM6125) },
{ qcom_board_id(IPQ8070A) },
{ qcom_board_id(IPQ8071A) },
{ qcom_board_id(IPQ6018) },
{ qcom_board_id(IPQ6028) },
{ qcom_board_id(IPQ6000) },
{ qcom_board_id(IPQ6010) },
{ qcom_board_id(SC7180) },
{ qcom_board_id(SM6350) },
{ qcom_board_id(SM8350) },
{ qcom_board_id(SC8280XP) },
{ qcom_board_id(IPQ6005) },
{ qcom_board_id(QRB5165) },
{ qcom_board_id(SM8450) },
{ qcom_board_id(SM7225) },
{ qcom_board_id(SA8295P) },
{ qcom_board_id(SA8540P) },
{ qcom_board_id_named(SM8450_2, "SM8450") },
{ qcom_board_id_named(SM8450_3, "SM8450") },
{ qcom_board_id(SC7280) },
{ qcom_board_id(SC7180P) },
{ qcom_board_id(SM6375) },
{ qcom_board_id(QRU1000) },
{ qcom_board_id(QDU1000) },
{ qcom_board_id(QDU1010) },
{ qcom_board_id(QRU1032) },
{ qcom_board_id(QRU1052) },
{ qcom_board_id(QRU1062) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
......
......@@ -98,6 +98,46 @@ static const struct spm_reg_data spm_reg_8916_cpu = {
.start_index[PM_SLEEP_MODE_SPC] = 5,
};
static const struct spm_reg_data spm_reg_8939_cpu = {
.reg_offset = spm_reg_offset_v3_0,
.spm_cfg = 0x1,
.spm_dly = 0x3C102800,
.seq = { 0x60, 0x03, 0x60, 0x0B, 0x0F, 0x20, 0x50, 0x1B, 0x10, 0x80,
0x30, 0x90, 0x5B, 0x60, 0x50, 0x03, 0x60, 0x76, 0x76, 0x0B,
0x50, 0x1B, 0x94, 0x5B, 0x80, 0x10, 0x26, 0x30, 0x50, 0x0F },
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 5,
};
static const u16 spm_reg_offset_v2_3[SPM_REG_NR] = {
[SPM_REG_CFG] = 0x08,
[SPM_REG_SPM_CTL] = 0x30,
[SPM_REG_DLY] = 0x34,
[SPM_REG_PMIC_DATA_0] = 0x40,
[SPM_REG_PMIC_DATA_1] = 0x44,
};
/* SPM register data for 8976 */
static const struct spm_reg_data spm_reg_8976_gold_l2 = {
.reg_offset = spm_reg_offset_v2_3,
.spm_cfg = 0x14,
.spm_dly = 0x3c11840a,
.pmic_data[0] = 0x03030080,
.pmic_data[1] = 0x00030000,
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 3,
};
static const struct spm_reg_data spm_reg_8976_silver_l2 = {
.reg_offset = spm_reg_offset_v2_3,
.spm_cfg = 0x14,
.spm_dly = 0x3c102800,
.pmic_data[0] = 0x03030080,
.pmic_data[1] = 0x00030000,
.start_index[PM_SLEEP_MODE_STBY] = 0,
.start_index[PM_SLEEP_MODE_SPC] = 2,
};
static const u16 spm_reg_offset_v2_1[SPM_REG_NR] = {
[SPM_REG_CFG] = 0x08,
[SPM_REG_SPM_CTL] = 0x30,
......@@ -211,8 +251,14 @@ static const struct of_device_id spm_match_table[] = {
.data = &spm_reg_8909_cpu },
{ .compatible = "qcom,msm8916-saw2-v3.0-cpu",
.data = &spm_reg_8916_cpu },
{ .compatible = "qcom,msm8939-saw2-v3.0-cpu",
.data = &spm_reg_8939_cpu },
{ .compatible = "qcom,msm8974-saw2-v2.1-cpu",
.data = &spm_reg_8974_8084_cpu },
{ .compatible = "qcom,msm8976-gold-saw2-v2.3-l2",
.data = &spm_reg_8976_gold_l2 },
{ .compatible = "qcom,msm8976-silver-saw2-v2.3-l2",
.data = &spm_reg_8976_silver_l2 },
{ .compatible = "qcom,msm8998-gold-saw2-v4.1-l2",
.data = &spm_reg_8998_gold_l2 },
{ .compatible = "qcom,msm8998-silver-saw2-v4.1-l2",
......
/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
/*
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
* Copyright (c) 2022 Linaro Ltd
* Author: Krzysztof Kozlowski <krzk@kernel.org> based on previous work of Kumar Gala.
*/
#ifndef _DT_BINDINGS_ARM_QCOM_IDS_H
#define _DT_BINDINGS_ARM_QCOM_IDS_H
/*
* The MSM chipset and hardware revision used by Qualcomm bootloaders, DTS for
* older chipsets (qcom,msm-id) and in socinfo driver:
*/
#define QCOM_ID_MSM8960 87
#define QCOM_ID_APQ8064 109
#define QCOM_ID_MSM8660A 122
#define QCOM_ID_MSM8260A 123
#define QCOM_ID_APQ8060A 124
#define QCOM_ID_MSM8974 126
#define QCOM_ID_MPQ8064 130
#define QCOM_ID_MSM8960AB 138
#define QCOM_ID_APQ8060AB 139
#define QCOM_ID_MSM8260AB 140
#define QCOM_ID_MSM8660AB 141
#define QCOM_ID_MSM8626 145
#define QCOM_ID_MSM8610 147
#define QCOM_ID_APQ8064AB 153
#define QCOM_ID_MSM8226 158
#define QCOM_ID_MSM8526 159
#define QCOM_ID_MSM8110 161
#define QCOM_ID_MSM8210 162
#define QCOM_ID_MSM8810 163
#define QCOM_ID_MSM8212 164
#define QCOM_ID_MSM8612 165
#define QCOM_ID_MSM8112 166
#define QCOM_ID_MSM8225Q 168
#define QCOM_ID_MSM8625Q 169
#define QCOM_ID_MSM8125Q 170
#define QCOM_ID_APQ8064AA 172
#define QCOM_ID_APQ8084 178
#define QCOM_ID_APQ8074 184
#define QCOM_ID_MSM8274 185
#define QCOM_ID_MSM8674 186
#define QCOM_ID_MSM8974PRO_AC 194
#define QCOM_ID_MSM8126 198
#define QCOM_ID_APQ8026 199
#define QCOM_ID_MSM8926 200
#define QCOM_ID_MSM8326 205
#define QCOM_ID_MSM8916 206
#define QCOM_ID_MSM8994 207
#define QCOM_ID_APQ8074PRO_AA 208
#define QCOM_ID_APQ8074PRO_AB 209
#define QCOM_ID_APQ8074PRO_AC 210
#define QCOM_ID_MSM8274PRO_AA 211
#define QCOM_ID_MSM8274PRO_AB 212
#define QCOM_ID_MSM8274PRO_AC 213
#define QCOM_ID_MSM8674PRO_AA 214
#define QCOM_ID_MSM8674PRO_AB 215
#define QCOM_ID_MSM8674PRO_AC 216
#define QCOM_ID_MSM8974PRO_AA 217
#define QCOM_ID_MSM8974PRO_AB 218
#define QCOM_ID_APQ8028 219
#define QCOM_ID_MSM8128 220
#define QCOM_ID_MSM8228 221
#define QCOM_ID_MSM8528 222
#define QCOM_ID_MSM8628 223
#define QCOM_ID_MSM8928 224
#define QCOM_ID_MSM8510 225
#define QCOM_ID_MSM8512 226
#define QCOM_ID_MSM8936 233
#define QCOM_ID_MSM8939 239
#define QCOM_ID_APQ8036 240
#define QCOM_ID_APQ8039 241
#define QCOM_ID_MSM8996 246
#define QCOM_ID_APQ8016 247
#define QCOM_ID_MSM8216 248
#define QCOM_ID_MSM8116 249
#define QCOM_ID_MSM8616 250
#define QCOM_ID_MSM8992 251
#define QCOM_ID_APQ8094 253
#define QCOM_ID_MDM9607 290
#define QCOM_ID_APQ8096 291
#define QCOM_ID_MSM8998 292
#define QCOM_ID_MSM8953 293
#define QCOM_ID_MDM8207 296
#define QCOM_ID_MDM9207 297
#define QCOM_ID_MDM9307 298
#define QCOM_ID_MDM9628 299
#define QCOM_ID_APQ8053 304
#define QCOM_ID_MSM8996SG 305
#define QCOM_ID_MSM8996AU 310
#define QCOM_ID_APQ8096AU 311
#define QCOM_ID_APQ8096SG 312
#define QCOM_ID_SDM660 317
#define QCOM_ID_SDM630 318
#define QCOM_ID_APQ8098 319
#define QCOM_ID_SDM845 321
#define QCOM_ID_MDM9206 322
#define QCOM_ID_IPQ8074 323
#define QCOM_ID_SDA660 324
#define QCOM_ID_SDM658 325
#define QCOM_ID_SDA658 326
#define QCOM_ID_SDA630 327
#define QCOM_ID_SDM450 338
#define QCOM_ID_SDA845 341
#define QCOM_ID_IPQ8072 342
#define QCOM_ID_IPQ8076 343
#define QCOM_ID_IPQ8078 344
#define QCOM_ID_SDM636 345
#define QCOM_ID_SDA636 346
#define QCOM_ID_SDM632 349
#define QCOM_ID_SDA632 350
#define QCOM_ID_SDA450 351
#define QCOM_ID_SM8250 356
#define QCOM_ID_IPQ8070 375
#define QCOM_ID_IPQ8071 376
#define QCOM_ID_IPQ8072A 389
#define QCOM_ID_IPQ8074A 390
#define QCOM_ID_IPQ8076A 391
#define QCOM_ID_IPQ8078A 392
#define QCOM_ID_SM6125 394
#define QCOM_ID_IPQ8070A 395
#define QCOM_ID_IPQ8071A 396
#define QCOM_ID_IPQ6018 402
#define QCOM_ID_IPQ6028 403
#define QCOM_ID_IPQ6000 421
#define QCOM_ID_IPQ6010 422
#define QCOM_ID_SC7180 425
#define QCOM_ID_SM6350 434
#define QCOM_ID_SM8350 439
#define QCOM_ID_SC8280XP 449
#define QCOM_ID_IPQ6005 453
#define QCOM_ID_QRB5165 455
#define QCOM_ID_SM8450 457
#define QCOM_ID_SM7225 459
#define QCOM_ID_SA8295P 460
#define QCOM_ID_SA8540P 461
#define QCOM_ID_SM8450_2 480
#define QCOM_ID_SM8450_3 482
#define QCOM_ID_SC7280 487
#define QCOM_ID_SC7180P 495
#define QCOM_ID_SM6375 507
#define QCOM_ID_QRU1000 539
#define QCOM_ID_QDU1000 545
#define QCOM_ID_QDU1010 587
#define QCOM_ID_QRU1032 588
#define QCOM_ID_QRU1052 589
#define QCOM_ID_QRU1062 590
/*
* The board type and revision information, used by Qualcomm bootloaders and
* DTS for older chipsets (qcom,board-id):
*/
#define QCOM_BOARD_ID(a, major, minor) \
(((major & 0xff) << 16) | ((minor & 0xff) << 8) | QCOM_BOARD_ID_##a)
#define QCOM_BOARD_ID_MTP 8
#define QCOM_BOARD_ID_DRAGONBOARD 10
#define QCOM_BOARD_ID_SBC 24
#endif /* _DT_BINDINGS_ARM_QCOM_IDS_H */
......@@ -4,6 +4,16 @@
#ifndef _DT_BINDINGS_POWER_QCOM_RPMPD_H
#define _DT_BINDINGS_POWER_QCOM_RPMPD_H
/* SDM670 Power Domain Indexes */
#define SDM670_MX 0
#define SDM670_MX_AO 1
#define SDM670_CX 2
#define SDM670_CX_AO 3
#define SDM670_LMX 4
#define SDM670_LCX 5
#define SDM670_GFX 6
#define SDM670_MSS 7
/* SDM845 Power Domain Indexes */
#define SDM845_EBI 0
#define SDM845_MX 1
......@@ -103,6 +113,12 @@
#define SM8450_MXC_AO 11
#define SM8450_MSS 12
/* QDU1000/QRU1000 Power Domain Indexes */
#define QDU1000_EBI 0
#define QDU1000_MSS 1
#define QDU1000_CX 2
#define QDU1000_MX 3
/* SC7180 Power Domain Indexes */
#define SC7180_CX 0
#define SC7180_CX_AO 1
......
......@@ -17,6 +17,7 @@
#include <linux/notifier.h>
#include <linux/spinlock.h>
#include <linux/cpumask.h>
#include <linux/time64.h>
/*
* Flags to control the behaviour of a genpd.
......@@ -95,6 +96,7 @@ struct genpd_governor_data {
s64 max_off_time_ns;
bool max_off_time_changed;
ktime_t next_wakeup;
ktime_t next_hrtimer;
bool cached_power_down_ok;
bool cached_power_down_state_idx;
};
......@@ -232,6 +234,7 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state);
int dev_pm_genpd_add_notifier(struct device *dev, struct notifier_block *nb);
int dev_pm_genpd_remove_notifier(struct device *dev);
void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next);
ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev);
extern struct dev_power_governor simple_qos_governor;
extern struct dev_power_governor pm_domain_always_on_gov;
......@@ -293,6 +296,10 @@ static inline int dev_pm_genpd_remove_notifier(struct device *dev)
static inline void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next)
{ }
static inline ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev)
{
return KTIME_MAX;
}
#define simple_qos_governor (*(struct dev_power_governor *)(NULL))
#define pm_domain_always_on_gov (*(struct dev_power_governor *)(NULL))
#endif
......
......@@ -26,18 +26,29 @@
#define PM8901_SUBTYPE 0x0f
#define PM8950_SUBTYPE 0x10
#define PMI8950_SUBTYPE 0x11
#define PMK8001_SUBTYPE 0x12
#define PMI8996_SUBTYPE 0x13
#define PM8998_SUBTYPE 0x14
#define PMI8998_SUBTYPE 0x15
#define PM8005_SUBTYPE 0x18
#define PM660L_SUBTYPE 0x1A
#define PM660_SUBTYPE 0x1B
#define PM8150_SUBTYPE 0x1E
#define PM660L_SUBTYPE 0x1a
#define PM660_SUBTYPE 0x1b
#define PM8150_SUBTYPE 0x1e
#define PM8150L_SUBTYPE 0x1f
#define PM8150B_SUBTYPE 0x20
#define PMK8002_SUBTYPE 0x21
#define PM8009_SUBTYPE 0x24
#define PMI632_SUBTYPE 0x25
#define PM8150C_SUBTYPE 0x26
#define PM6150_SUBTYPE 0x28
#define SMB2351_SUBTYPE 0x29
#define PM8008_SUBTYPE 0x2c
#define PM6125_SUBTYPE 0x2d
#define PM7250B_SUBTYPE 0x2e
#define PMK8350_SUBTYPE 0x2f
#define PMR735B_SUBTYPE 0x34
#define PM6350_SUBTYPE 0x36
#define PM2250_SUBTYPE 0x37
#define PMI8998_FAB_ID_SMIC 0x11
#define PMI8998_FAB_ID_GF 0x30
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment