Commit ad4e807f authored by Bjorn Andersson's avatar Bjorn Andersson

Merge branch '20230526-topic-smd_icc-v7-0-09c78c175546@linaro.org' into clk-for-6.6

This series reshuffles things around, moving the management of SMD RPM
bus clocks to the interconnect framework where they belong. This helps
us solve a couple of issues:

1. We can work towards unused clk cleanup of RPMCC without worrying
   about it killing some NoC bus, resulting in the SoC dying.
   Deasserting actually unused RPM clocks (among other things) will
   let us achieve "true SoC-wide power collapse states", also known as
   VDD_LOW and VDD_MIN.

2. We no longer have to keep tons of quirky bus clock ifs in the icc
   driver. You either have a RPM clock and call "rpm set rate" or you
   have a single non-RPM clock (like AHB_CLK_SRC) or you don't have any.

3. There's less overhead - instead of going through layers and layers of
   the CCF, ratesetting comes down to calling max() and sending a single
   RPM message. ICC is very very dynamic so that's a big plus.

The clocks still need to be vaguely described in the clk-smd-rpm driver,
as it gives them an initial kickoff, before actually telling RPM to
enable DVFS scaling.  After RPM receives that command, all clocks that
have not been assigned a rate are considered unused and are shut down
in hardware, leading to the same issue as described in point 1.

We can consider marking them __initconst in the future, but this series
is very fat even without that..

Apart from that, it squashes a couple of bugs that really need fixing..

The series is merged through a topic branch to manage the dependencies
between interconnect, Qualcomm clocks and Qualcomm SoC.
parents db382dd5 17fc623e
This diff is collapsed.
......@@ -29,7 +29,7 @@ qnoc-sm8250-objs := sm8250.o
qnoc-sm8350-objs := sm8350.o
qnoc-sm8450-objs := sm8450.o
qnoc-sm8550-objs := sm8550.o
icc-smd-rpm-objs := smd-rpm.o icc-rpm.o
icc-smd-rpm-objs := smd-rpm.o icc-rpm.o icc-rpm-clocks.o
obj-$(CONFIG_INTERCONNECT_QCOM_BCM_VOTER) += icc-bcm-voter.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8916) += qnoc-msm8916.o
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2023 Linaro Ltd
*/
#include <linux/soc/qcom/smd-rpm.h>
#include "icc-rpm.h"
const struct rpm_clk_resource aggre1_clk = {
.resource_type = QCOM_SMD_RPM_AGGR_CLK,
.clock_id = 1,
};
EXPORT_SYMBOL_GPL(aggre1_clk);
const struct rpm_clk_resource aggre2_clk = {
.resource_type = QCOM_SMD_RPM_AGGR_CLK,
.clock_id = 2,
};
EXPORT_SYMBOL_GPL(aggre2_clk);
const struct rpm_clk_resource bimc_clk = {
.resource_type = QCOM_SMD_RPM_MEM_CLK,
.clock_id = 0,
};
EXPORT_SYMBOL_GPL(bimc_clk);
const struct rpm_clk_resource bus_0_clk = {
.resource_type = QCOM_SMD_RPM_BUS_CLK,
.clock_id = 0,
};
EXPORT_SYMBOL_GPL(bus_0_clk);
const struct rpm_clk_resource bus_1_clk = {
.resource_type = QCOM_SMD_RPM_BUS_CLK,
.clock_id = 1,
};
EXPORT_SYMBOL_GPL(bus_1_clk);
const struct rpm_clk_resource bus_2_clk = {
.resource_type = QCOM_SMD_RPM_BUS_CLK,
.clock_id = 2,
};
EXPORT_SYMBOL_GPL(bus_2_clk);
const struct rpm_clk_resource mmaxi_0_clk = {
.resource_type = QCOM_SMD_RPM_MMAXI_CLK,
.clock_id = 0,
};
EXPORT_SYMBOL_GPL(mmaxi_0_clk);
const struct rpm_clk_resource mmaxi_1_clk = {
.resource_type = QCOM_SMD_RPM_MMAXI_CLK,
.clock_id = 1,
};
EXPORT_SYMBOL_GPL(mmaxi_1_clk);
const struct rpm_clk_resource qup_clk = {
.resource_type = QCOM_SMD_RPM_QUP_CLK,
.clock_id = 0,
};
EXPORT_SYMBOL_GPL(qup_clk);
/* Branch clocks */
const struct rpm_clk_resource aggre1_branch_clk = {
.resource_type = QCOM_SMD_RPM_AGGR_CLK,
.clock_id = 1,
.branch = true,
};
EXPORT_SYMBOL_GPL(aggre1_branch_clk);
const struct rpm_clk_resource aggre2_branch_clk = {
.resource_type = QCOM_SMD_RPM_AGGR_CLK,
.clock_id = 2,
.branch = true,
};
EXPORT_SYMBOL_GPL(aggre2_branch_clk);
This diff is collapsed.
......@@ -6,7 +6,12 @@
#ifndef __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H
#define __DRIVERS_INTERCONNECT_QCOM_ICC_RPM_H
#include <dt-bindings/interconnect/qcom,icc.h>
#include <linux/soc/qcom/smd-rpm.h>
#include <dt-bindings/interconnect/qcom,rpm-icc.h>
#include <linux/clk.h>
#include <linux/interconnect-provider.h>
#include <linux/platform_device.h>
#define RPM_BUS_MASTER_REQ 0x73616d62
#define RPM_BUS_SLAVE_REQ 0x766c7362
......@@ -20,31 +25,43 @@ enum qcom_icc_type {
QCOM_ICC_QNOC,
};
#define NUM_BUS_CLKS 2
/**
* struct rpm_clk_resource - RPM bus clock resource
* @resource_type: RPM resource type of the clock resource
* @clock_id: index of the clock resource of a specific resource type
* @branch: whether the resource represents a branch clock
*/
struct rpm_clk_resource {
u32 resource_type;
u32 clock_id;
bool branch;
};
/**
* struct qcom_icc_provider - Qualcomm specific interconnect provider
* @provider: generic interconnect provider
* @num_bus_clks: the total number of bus_clks clk_bulk_data entries (0 or 2)
* @num_intf_clks: the total number of intf_clks clk_bulk_data entries
* @type: the ICC provider type
* @regmap: regmap for QoS registers read/write access
* @qos_offset: offset to QoS registers
* @bus_clk_rate: bus clock rate in Hz
* @bus_clks: the clk_bulk_data table of bus clocks
* @bus_clk_desc: a pointer to a rpm_clk_resource description of bus clocks
* @bus_clk: a pointer to a HLOS-owned bus clock
* @intf_clks: a clk_bulk_data array of interface clocks
* @keep_alive: whether to always keep a minimum vote on the bus clocks
* @is_on: whether the bus is powered on
*/
struct qcom_icc_provider {
struct icc_provider provider;
int num_bus_clks;
int num_intf_clks;
enum qcom_icc_type type;
struct regmap *regmap;
unsigned int qos_offset;
u64 bus_clk_rate[NUM_BUS_CLKS];
struct clk_bulk_data bus_clks[NUM_BUS_CLKS];
u32 bus_clk_rate[QCOM_SMD_RPM_STATE_NUM];
const struct rpm_clk_resource *bus_clk_desc;
struct clk *bus_clk;
struct clk_bulk_data *intf_clks;
bool keep_alive;
bool is_on;
};
......@@ -89,8 +106,8 @@ struct qcom_icc_node {
u16 num_links;
u16 channels;
u16 buswidth;
u64 sum_avg[QCOM_ICC_NUM_BUCKETS];
u64 max_peak[QCOM_ICC_NUM_BUCKETS];
u64 sum_avg[QCOM_SMD_RPM_STATE_NUM];
u64 max_peak[QCOM_SMD_RPM_STATE_NUM];
int mas_rpm_id;
int slv_rpm_id;
struct qcom_icc_qos qos;
......@@ -99,10 +116,10 @@ struct qcom_icc_node {
struct qcom_icc_desc {
struct qcom_icc_node * const *nodes;
size_t num_nodes;
const char * const *bus_clocks;
const struct rpm_clk_resource *bus_clk_desc;
const char * const *intf_clocks;
size_t num_intf_clocks;
bool no_clk_scaling;
bool keep_alive;
enum qcom_icc_type type;
const struct regmap_config *regmap_cfg;
unsigned int qos_offset;
......@@ -115,7 +132,24 @@ enum qos_mode {
NOC_QOS_MODE_BYPASS,
};
extern const struct rpm_clk_resource aggre1_clk;
extern const struct rpm_clk_resource aggre2_clk;
extern const struct rpm_clk_resource bimc_clk;
extern const struct rpm_clk_resource bus_0_clk;
extern const struct rpm_clk_resource bus_1_clk;
extern const struct rpm_clk_resource bus_2_clk;
extern const struct rpm_clk_resource mmaxi_0_clk;
extern const struct rpm_clk_resource mmaxi_1_clk;
extern const struct rpm_clk_resource qup_clk;
extern const struct rpm_clk_resource aggre1_branch_clk;
extern const struct rpm_clk_resource aggre2_branch_clk;
int qnoc_probe(struct platform_device *pdev);
int qnoc_remove(struct platform_device *pdev);
bool qcom_icc_rpm_smd_available(void);
int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val);
int qcom_icc_rpm_set_bus_rate(const struct rpm_clk_resource *clk, int ctx, u32 rate);
#endif
......@@ -4,7 +4,6 @@
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
......@@ -15,7 +14,6 @@
#include <dt-bindings/interconnect/qcom,msm8916.h>
#include "smd-rpm.h"
#include "icc-rpm.h"
enum {
......@@ -1232,6 +1230,7 @@ static const struct qcom_icc_desc msm8916_snoc = {
.type = QCOM_ICC_NOC,
.nodes = msm8916_snoc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_snoc_nodes),
.bus_clk_desc = &bus_1_clk,
.regmap_cfg = &msm8916_snoc_regmap_config,
.qos_offset = 0x7000,
};
......@@ -1260,6 +1259,7 @@ static const struct qcom_icc_desc msm8916_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = msm8916_bimc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &msm8916_bimc_regmap_config,
.qos_offset = 0x8000,
};
......@@ -1329,6 +1329,7 @@ static const struct qcom_icc_desc msm8916_pcnoc = {
.type = QCOM_ICC_NOC,
.nodes = msm8916_pcnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8916_pcnoc_nodes),
.bus_clk_desc = &bus_0_clk,
.regmap_cfg = &msm8916_pcnoc_regmap_config,
.qos_offset = 0x7000,
};
......
......@@ -5,7 +5,6 @@
* With reference of msm8916 interconnect driver of Georgi Djakov.
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
......@@ -16,7 +15,6 @@
#include <dt-bindings/interconnect/qcom,msm8939.h>
#include "smd-rpm.h"
#include "icc-rpm.h"
enum {
......@@ -1285,6 +1283,7 @@ static const struct qcom_icc_desc msm8939_snoc = {
.type = QCOM_ICC_NOC,
.nodes = msm8939_snoc_nodes,
.num_nodes = ARRAY_SIZE(msm8939_snoc_nodes),
.bus_clk_desc = &bus_1_clk,
.regmap_cfg = &msm8939_snoc_regmap_config,
.qos_offset = 0x7000,
};
......@@ -1305,6 +1304,7 @@ static const struct qcom_icc_desc msm8939_snoc_mm = {
.type = QCOM_ICC_NOC,
.nodes = msm8939_snoc_mm_nodes,
.num_nodes = ARRAY_SIZE(msm8939_snoc_mm_nodes),
.bus_clk_desc = &bus_2_clk,
.regmap_cfg = &msm8939_snoc_regmap_config,
.qos_offset = 0x7000,
};
......@@ -1333,6 +1333,7 @@ static const struct qcom_icc_desc msm8939_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = msm8939_bimc_nodes,
.num_nodes = ARRAY_SIZE(msm8939_bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &msm8939_bimc_regmap_config,
.qos_offset = 0x8000,
};
......@@ -1404,6 +1405,7 @@ static const struct qcom_icc_desc msm8939_pcnoc = {
.type = QCOM_ICC_NOC,
.nodes = msm8939_pcnoc_nodes,
.num_nodes = ARRAY_SIZE(msm8939_pcnoc_nodes),
.bus_clk_desc = &bus_0_clk,
.regmap_cfg = &msm8939_pcnoc_regmap_config,
.qos_offset = 0x7000,
};
......
......@@ -38,7 +38,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "smd-rpm.h"
#include "icc-rpm.h"
enum {
MSM8974_BIMC_MAS_AMPSS_M0 = 1,
......
......@@ -5,7 +5,6 @@
* Copyright (c) 2021 Yassine Oudjana <y.oudjana@protonmail.com>
*/
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
......@@ -18,7 +17,6 @@
#include <dt-bindings/interconnect/qcom,msm8996.h>
#include "icc-rpm.h"
#include "smd-rpm.h"
#include "msm8996.h"
static const char * const mm_intf_clocks[] = {
......@@ -1819,7 +1817,6 @@ static const struct qcom_icc_desc msm8996_a0noc = {
.num_nodes = ARRAY_SIZE(a0noc_nodes),
.intf_clocks = a0noc_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(a0noc_intf_clocks),
.no_clk_scaling = true,
.regmap_cfg = &msm8996_a0noc_regmap_config
};
......@@ -1841,6 +1838,7 @@ static const struct qcom_icc_desc msm8996_a1noc = {
.type = QCOM_ICC_NOC,
.nodes = a1noc_nodes,
.num_nodes = ARRAY_SIZE(a1noc_nodes),
.bus_clk_desc = &aggre1_branch_clk,
.regmap_cfg = &msm8996_a1noc_regmap_config
};
......@@ -1862,6 +1860,7 @@ static const struct qcom_icc_desc msm8996_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = a2noc_nodes,
.num_nodes = ARRAY_SIZE(a2noc_nodes),
.bus_clk_desc = &aggre2_branch_clk,
.intf_clocks = a2noc_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &msm8996_a2noc_regmap_config
......@@ -1890,6 +1889,7 @@ static const struct qcom_icc_desc msm8996_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = bimc_nodes,
.num_nodes = ARRAY_SIZE(bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &msm8996_bimc_regmap_config
};
......@@ -1948,6 +1948,7 @@ static const struct qcom_icc_desc msm8996_cnoc = {
.type = QCOM_ICC_NOC,
.nodes = cnoc_nodes,
.num_nodes = ARRAY_SIZE(cnoc_nodes),
.bus_clk_desc = &bus_2_clk,
.regmap_cfg = &msm8996_cnoc_regmap_config
};
......@@ -2001,6 +2002,7 @@ static const struct qcom_icc_desc msm8996_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = mnoc_nodes,
.num_nodes = ARRAY_SIZE(mnoc_nodes),
.bus_clk_desc = &mmaxi_0_clk,
.intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &msm8996_mnoc_regmap_config
......@@ -2039,6 +2041,7 @@ static const struct qcom_icc_desc msm8996_pnoc = {
.type = QCOM_ICC_NOC,
.nodes = pnoc_nodes,
.num_nodes = ARRAY_SIZE(pnoc_nodes),
.bus_clk_desc = &bus_0_clk,
.regmap_cfg = &msm8996_pnoc_regmap_config
};
......@@ -2083,6 +2086,7 @@ static const struct qcom_icc_desc msm8996_snoc = {
.type = QCOM_ICC_NOC,
.nodes = snoc_nodes,
.num_nodes = ARRAY_SIZE(snoc_nodes),
.bus_clk_desc = &bus_1_clk,
.regmap_cfg = &msm8996_snoc_regmap_config
};
......
......@@ -7,7 +7,6 @@
*/
#include <dt-bindings/interconnect/qcom,qcm2290.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
......@@ -19,7 +18,6 @@
#include <linux/slab.h>
#include "icc-rpm.h"
#include "smd-rpm.h"
enum {
QCM2290_MASTER_APPSS_PROC = 1,
......@@ -1197,6 +1195,7 @@ static const struct qcom_icc_desc qcm2290_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = qcm2290_bimc_nodes,
.num_nodes = ARRAY_SIZE(qcm2290_bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &qcm2290_bimc_regmap_config,
/* M_REG_BASE() in vendor msm_bus_bimc_adhoc driver */
.qos_offset = 0x8000,
......@@ -1252,6 +1251,7 @@ static const struct qcom_icc_desc qcm2290_cnoc = {
.type = QCOM_ICC_NOC,
.nodes = qcm2290_cnoc_nodes,
.num_nodes = ARRAY_SIZE(qcm2290_cnoc_nodes),
.bus_clk_desc = &bus_1_clk,
.regmap_cfg = &qcm2290_cnoc_regmap_config,
};
......@@ -1293,6 +1293,7 @@ static const struct qcom_icc_desc qcm2290_snoc = {
.type = QCOM_ICC_QNOC,
.nodes = qcm2290_snoc_nodes,
.num_nodes = ARRAY_SIZE(qcm2290_snoc_nodes),
.bus_clk_desc = &bus_2_clk,
.regmap_cfg = &qcm2290_snoc_regmap_config,
/* Vendor DT node fab-sys_noc property 'qcom,base-offset' */
.qos_offset = 0x15000,
......@@ -1307,6 +1308,7 @@ static const struct qcom_icc_desc qcm2290_qup_virt = {
.type = QCOM_ICC_QNOC,
.nodes = qcm2290_qup_virt_nodes,
.num_nodes = ARRAY_SIZE(qcm2290_qup_virt_nodes),
.bus_clk_desc = &qup_clk,
};
static struct qcom_icc_node * const qcm2290_mmnrt_virt_nodes[] = {
......@@ -1320,6 +1322,7 @@ static const struct qcom_icc_desc qcm2290_mmnrt_virt = {
.type = QCOM_ICC_QNOC,
.nodes = qcm2290_mmnrt_virt_nodes,
.num_nodes = ARRAY_SIZE(qcm2290_mmnrt_virt_nodes),
.bus_clk_desc = &mmaxi_0_clk,
.regmap_cfg = &qcm2290_snoc_regmap_config,
.qos_offset = 0x15000,
};
......@@ -1334,6 +1337,7 @@ static const struct qcom_icc_desc qcm2290_mmrt_virt = {
.type = QCOM_ICC_QNOC,
.nodes = qcm2290_mmrt_virt_nodes,
.num_nodes = ARRAY_SIZE(qcm2290_mmrt_virt_nodes),
.bus_clk_desc = &mmaxi_1_clk,
.regmap_cfg = &qcm2290_snoc_regmap_config,
.qos_offset = 0x15000,
};
......
......@@ -4,7 +4,6 @@
*/
#include <dt-bindings/interconnect/qcom,qcs404.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
......@@ -13,7 +12,6 @@
#include <linux/of_device.h>
#include "smd-rpm.h"
#include "icc-rpm.h"
enum {
......@@ -985,6 +983,7 @@ static struct qcom_icc_node * const qcs404_bimc_nodes[] = {
};
static const struct qcom_icc_desc qcs404_bimc = {
.bus_clk_desc = &bimc_clk,
.nodes = qcs404_bimc_nodes,
.num_nodes = ARRAY_SIZE(qcs404_bimc_nodes),
};
......@@ -1039,6 +1038,7 @@ static struct qcom_icc_node * const qcs404_pcnoc_nodes[] = {
};
static const struct qcom_icc_desc qcs404_pcnoc = {
.bus_clk_desc = &bus_0_clk,
.nodes = qcs404_pcnoc_nodes,
.num_nodes = ARRAY_SIZE(qcs404_pcnoc_nodes),
};
......@@ -1067,6 +1067,7 @@ static struct qcom_icc_node * const qcs404_snoc_nodes[] = {
};
static const struct qcom_icc_desc qcs404_snoc = {
.bus_clk_desc = &bus_1_clk,
.nodes = qcs404_snoc_nodes,
.num_nodes = ARRAY_SIZE(qcs404_snoc_nodes),
};
......
......@@ -5,7 +5,6 @@
*/
#include <dt-bindings/interconnect/qcom,sdm660.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/interconnect-provider.h>
#include <linux/io.h>
......@@ -17,7 +16,6 @@
#include <linux/slab.h>
#include "icc-rpm.h"
#include "smd-rpm.h"
enum {
SDM660_MASTER_IPA = 1,
......@@ -1512,6 +1510,7 @@ static const struct qcom_icc_desc sdm660_a2noc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_a2noc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_a2noc_nodes),
.bus_clk_desc = &aggre2_clk,
.intf_clocks = a2noc_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(a2noc_intf_clocks),
.regmap_cfg = &sdm660_a2noc_regmap_config,
......@@ -1540,6 +1539,7 @@ static const struct qcom_icc_desc sdm660_bimc = {
.type = QCOM_ICC_BIMC,
.nodes = sdm660_bimc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_bimc_nodes),
.bus_clk_desc = &bimc_clk,
.regmap_cfg = &sdm660_bimc_regmap_config,
};
......@@ -1594,6 +1594,7 @@ static const struct qcom_icc_desc sdm660_cnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_cnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_cnoc_nodes),
.bus_clk_desc = &bus_2_clk,
.regmap_cfg = &sdm660_cnoc_regmap_config,
};
......@@ -1616,7 +1617,6 @@ static const struct qcom_icc_desc sdm660_gnoc = {
.nodes = sdm660_gnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_gnoc_nodes),
.regmap_cfg = &sdm660_gnoc_regmap_config,
.no_clk_scaling = true,
};
static struct qcom_icc_node * const sdm660_mnoc_nodes[] = {
......@@ -1656,6 +1656,7 @@ static const struct qcom_icc_desc sdm660_mnoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_mnoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_mnoc_nodes),
.bus_clk_desc = &mmaxi_0_clk,
.intf_clocks = mm_intf_clocks,
.num_intf_clocks = ARRAY_SIZE(mm_intf_clocks),
.regmap_cfg = &sdm660_mnoc_regmap_config,
......@@ -1693,6 +1694,7 @@ static const struct qcom_icc_desc sdm660_snoc = {
.type = QCOM_ICC_NOC,
.nodes = sdm660_snoc_nodes,
.num_nodes = ARRAY_SIZE(sdm660_snoc_nodes),
.bus_clk_desc = &bus_1_clk,
.regmap_cfg = &sdm660_snoc_regmap_config,
};
......
......@@ -13,9 +13,10 @@
#include <linux/platform_device.h>
#include <linux/soc/qcom/smd-rpm.h>
#include "smd-rpm.h"
#include "icc-rpm.h"
#define RPM_KEY_BW 0x00007762
#define QCOM_RPM_SMD_KEY_RATE 0x007a484b
static struct qcom_smd_rpm *icc_smd_rpm;
......@@ -44,6 +45,26 @@ int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val)
}
EXPORT_SYMBOL_GPL(qcom_icc_rpm_smd_send);
int qcom_icc_rpm_set_bus_rate(const struct rpm_clk_resource *clk, int ctx, u32 rate)
{
struct clk_smd_rpm_req req = {
.key = cpu_to_le32(QCOM_RPM_SMD_KEY_RATE),
.nbytes = cpu_to_le32(sizeof(u32)),
};
/* Branch clocks are only on/off */
if (clk->branch)
rate = !!rate;
req.value = cpu_to_le32(rate);
return qcom_rpm_smd_write(icc_smd_rpm,
ctx,
clk->resource_type,
clk->clock_id,
&req, sizeof(req));
}
EXPORT_SYMBOL_GPL(qcom_icc_rpm_set_bus_rate);
static int qcom_icc_rpm_smd_remove(struct platform_device *pdev)
{
icc_smd_rpm = NULL;
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019, Linaro Ltd.
* Author: Georgi Djakov <georgi.djakov@linaro.org>
*/
#ifndef __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H
#define __DRIVERS_INTERCONNECT_QCOM_SMD_RPM_H
#include <linux/soc/qcom/smd-rpm.h>
bool qcom_icc_rpm_smd_available(void);
int qcom_icc_rpm_smd_send(int ctx, int rsc_type, int id, u32 val);
#endif
......@@ -19,7 +19,6 @@
/**
* struct qcom_smd_rpm - state of the rpm device driver
* @rpm_channel: reference to the smd channel
* @icc: interconnect proxy device
* @dev: rpm device
* @ack: completion for acks
* @lock: mutual exclusion around the send/complete pair
......@@ -27,7 +26,6 @@
*/
struct qcom_smd_rpm {
struct rpmsg_endpoint *rpm_channel;
struct platform_device *icc;
struct device *dev;
struct completion ack;
......@@ -197,7 +195,6 @@ static int qcom_smd_rpm_callback(struct rpmsg_device *rpdev,
static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
{
struct qcom_smd_rpm *rpm;
int ret;
rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL);
if (!rpm)
......@@ -210,23 +207,11 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
rpm->rpm_channel = rpdev->ept;
dev_set_drvdata(&rpdev->dev, rpm);
rpm->icc = platform_device_register_data(&rpdev->dev, "icc_smd_rpm", -1,
NULL, 0);
if (IS_ERR(rpm->icc))
return PTR_ERR(rpm->icc);
ret = of_platform_populate(rpdev->dev.of_node, NULL, NULL, &rpdev->dev);
if (ret)
platform_device_unregister(rpm->icc);
return ret;
return of_platform_populate(rpdev->dev.of_node, NULL, NULL, &rpdev->dev);
}
static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
{
struct qcom_smd_rpm *rpm = dev_get_drvdata(&rpdev->dev);
platform_device_unregister(rpm->icc);
of_platform_depopulate(&rpdev->dev);
}
......
/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
/*
* Copyright (c) 2023, Linaro Limited
*/
#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_RPM_ICC_H
#define __DT_BINDINGS_INTERCONNECT_QCOM_RPM_ICC_H
#define RPM_ACTIVE_TAG (1 << 0)
#define RPM_SLEEP_TAG (1 << 1)
#define RPM_ALWAYS_TAG (RPM_ACTIVE_TAG | RPM_SLEEP_TAG)
#endif
......@@ -2,10 +2,13 @@
#ifndef __QCOM_SMD_RPM_H__
#define __QCOM_SMD_RPM_H__
#include <linux/types.h>
struct qcom_smd_rpm;
#define QCOM_SMD_RPM_ACTIVE_STATE 0
#define QCOM_SMD_RPM_SLEEP_STATE 1
#define QCOM_SMD_RPM_ACTIVE_STATE 0
#define QCOM_SMD_RPM_SLEEP_STATE 1
#define QCOM_SMD_RPM_STATE_NUM 2
/*
* Constants used for addressing resources in the RPM.
......@@ -44,6 +47,19 @@ struct qcom_smd_rpm;
#define QCOM_SMD_RPM_PKA_CLK 0x616b70
#define QCOM_SMD_RPM_MCFG_CLK 0x6766636d
#define QCOM_RPM_KEY_SOFTWARE_ENABLE 0x6e657773
#define QCOM_RPM_KEY_PIN_CTRL_CLK_BUFFER_ENABLE_KEY 0x62636370
#define QCOM_RPM_SMD_KEY_RATE 0x007a484b
#define QCOM_RPM_SMD_KEY_ENABLE 0x62616e45
#define QCOM_RPM_SMD_KEY_STATE 0x54415453
#define QCOM_RPM_SCALING_ENABLE_ID 0x2
struct clk_smd_rpm_req {
__le32 key;
__le32 nbytes;
__le32 value;
};
int qcom_rpm_smd_write(struct qcom_smd_rpm *rpm,
int state,
u32 resource_type, u32 resource_id,
......
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