Commit 01f8938a authored by Georgi Djakov's avatar Georgi Djakov
Browse files

Merge branch 'icc-qcm2290' into icc-next

Add support for QCM2290 including a few prep changes.

* icc-qcm2290
  interconnect: icc-rpm: Define ICC device type
  interconnect: icc-rpm: Add QNOC type QoS support
  interconnect: icc-rpm: Support child NoC device probe
  dt-bindings: interconnect: Add Qualcomm QCM2290 NoC support
  interconnect: qcom: Add QCM2290 driver support

Link: https://lore.kernel.org/r/20211215002324.1727-1-shawn.guo@linaro.org


Signed-off-by: default avatarGeorgi Djakov <djakov@kernel.org>
parents 4a5cf65d 1a14b1ac
Loading
Loading
Loading
Loading
+137 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/interconnect/qcom,qcm2290.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Qualcomm QCM2290 Network-On-Chip interconnect

maintainers:
  - Shawn Guo <shawn.guo@linaro.org>

description: |
  The Qualcomm QCM2290 interconnect providers support adjusting the
  bandwidth requirements between the various NoC fabrics.

properties:
  reg:
    maxItems: 1

  compatible:
    enum:
      - qcom,qcm2290-bimc
      - qcom,qcm2290-cnoc
      - qcom,qcm2290-snoc

  '#interconnect-cells':
    const: 1

  clock-names:
    items:
      - const: bus
      - const: bus_a

  clocks:
    items:
      - description: Bus Clock
      - description: Bus A Clock

# Child node's properties
patternProperties:
  '^interconnect-[a-z0-9]+$':
    type: object
    description:
      The interconnect providers do not have a separate QoS register space,
      but share parent's space.

    properties:
      compatible:
        enum:
          - qcom,qcm2290-qup-virt
          - qcom,qcm2290-mmrt-virt
          - qcom,qcm2290-mmnrt-virt

      '#interconnect-cells':
        const: 1

      clock-names:
        items:
          - const: bus
          - const: bus_a

      clocks:
        items:
          - description: Bus Clock
          - description: Bus A Clock

    required:
      - compatible
      - '#interconnect-cells'
      - clock-names
      - clocks

    additionalProperties: false

required:
  - compatible
  - reg
  - '#interconnect-cells'
  - clock-names
  - clocks

additionalProperties: false

examples:
  - |
    #include <dt-bindings/clock/qcom,rpmcc.h>

    snoc: interconnect@1880000 {
        compatible = "qcom,qcm2290-snoc";
        reg = <0x01880000 0x60200>;
        #interconnect-cells = <1>;
        clock-names = "bus", "bus_a";
        clocks = <&rpmcc RPM_SMD_SNOC_CLK>,
                 <&rpmcc RPM_SMD_SNOC_A_CLK>;

        qup_virt: interconnect-qup {
            compatible = "qcom,qcm2290-qup-virt";
            #interconnect-cells = <1>;
            clock-names = "bus", "bus_a";
            clocks = <&rpmcc RPM_SMD_QUP_CLK>,
                     <&rpmcc RPM_SMD_QUP_A_CLK>;
        };

        mmnrt_virt: interconnect-mmnrt {
            compatible = "qcom,qcm2290-mmnrt-virt";
            #interconnect-cells = <1>;
            clock-names = "bus", "bus_a";
            clocks = <&rpmcc RPM_SMD_MMNRT_CLK>,
                     <&rpmcc RPM_SMD_MMNRT_A_CLK>;
        };

        mmrt_virt: interconnect-mmrt {
            compatible = "qcom,qcm2290-mmrt-virt";
            #interconnect-cells = <1>;
            clock-names = "bus", "bus_a";
            clocks = <&rpmcc RPM_SMD_MMRT_CLK>,
                     <&rpmcc RPM_SMD_MMRT_A_CLK>;
        };
    };

    cnoc: interconnect@1900000 {
        compatible = "qcom,qcm2290-cnoc";
        reg = <0x01900000 0x8200>;
        #interconnect-cells = <1>;
        clock-names = "bus", "bus_a";
        clocks = <&rpmcc RPM_SMD_CNOC_CLK>,
                 <&rpmcc RPM_SMD_CNOC_A_CLK>;
    };

    bimc: interconnect@4480000 {
        compatible = "qcom,qcm2290-bimc";
        reg = <0x04480000 0x80000>;
        #interconnect-cells = <1>;
        clock-names = "bus", "bus_a";
        clocks = <&rpmcc RPM_SMD_BIMC_CLK>,
                 <&rpmcc RPM_SMD_BIMC_A_CLK>;
    };
+9 −0
Original line number Diff line number Diff line
@@ -51,6 +51,15 @@ config INTERCONNECT_QCOM_OSM_L3
	  Say y here to support the Operating State Manager (OSM) interconnect
	  driver which controls the scaling of L3 caches on Qualcomm SoCs.

config INTERCONNECT_QCOM_QCM2290
	tristate "Qualcomm QCM2290 interconnect driver"
	depends on INTERCONNECT_QCOM
	depends on QCOM_SMD_RPM
	select INTERCONNECT_QCOM_SMD_RPM
	help
	  This is a driver for the Qualcomm Network-on-Chip on qcm2290-based
	  platforms.

config INTERCONNECT_QCOM_QCS404
	tristate "Qualcomm QCS404 interconnect driver"
	depends on INTERCONNECT_QCOM
+2 −0
Original line number Diff line number Diff line
@@ -6,6 +6,7 @@ qnoc-msm8939-objs := msm8939.o
qnoc-msm8974-objs			:= msm8974.o
qnoc-msm8996-objs			:= msm8996.o
icc-osm-l3-objs				:= osm-l3.o
qnoc-qcm2290-objs			:= qcm2290.o
qnoc-qcs404-objs			:= qcs404.o
icc-rpmh-obj				:= icc-rpmh.o
qnoc-sc7180-objs			:= sc7180.o
@@ -26,6 +27,7 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8939) += qnoc-msm8939.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8974) += qnoc-msm8974.o
obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o
+47 −5
Original line number Diff line number Diff line
@@ -18,6 +18,13 @@
#include "smd-rpm.h"
#include "icc-rpm.h"

/* QNOC QoS */
#define QNOC_QOS_MCTL_LOWn_ADDR(n)	(0x8 + (n * 0x1000))
#define QNOC_QOS_MCTL_DFLT_PRIO_MASK	0x70
#define QNOC_QOS_MCTL_DFLT_PRIO_SHIFT	4
#define QNOC_QOS_MCTL_URGFWD_EN_MASK	0x8
#define QNOC_QOS_MCTL_URGFWD_EN_SHIFT	3

/* BIMC QoS */
#define M_BKE_REG_BASE(n)		(0x300 + (0x4000 * n))
#define M_BKE_EN_ADDR(n)		(M_BKE_REG_BASE(n))
@@ -40,6 +47,27 @@
#define NOC_QOS_MODEn_ADDR(n)		(0xc + (n * 0x1000))
#define NOC_QOS_MODEn_MASK		0x3

static int qcom_icc_set_qnoc_qos(struct icc_node *src, u64 max_bw)
{
	struct icc_provider *provider = src->provider;
	struct qcom_icc_provider *qp = to_qcom_provider(provider);
	struct qcom_icc_node *qn = src->data;
	struct qcom_icc_qos *qos = &qn->qos;
	int rc;

	rc = regmap_update_bits(qp->regmap,
			qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
			QNOC_QOS_MCTL_DFLT_PRIO_MASK,
			qos->areq_prio << QNOC_QOS_MCTL_DFLT_PRIO_SHIFT);
	if (rc)
		return rc;

	return regmap_update_bits(qp->regmap,
			qp->qos_offset + QNOC_QOS_MCTL_LOWn_ADDR(qos->qos_port),
			QNOC_QOS_MCTL_URGFWD_EN_MASK,
			!!qos->urg_fwd_en << QNOC_QOS_MCTL_URGFWD_EN_SHIFT);
}

static int qcom_icc_bimc_set_qos_health(struct qcom_icc_provider *qp,
					struct qcom_icc_qos *qos,
					int regnum)
@@ -164,11 +192,15 @@ static int qcom_icc_qos_set(struct icc_node *node, u64 sum_bw)

	dev_dbg(node->provider->dev, "Setting QoS for %s\n", qn->name);

	if (qp->is_bimc_node)
	switch (qp->type) {
	case QCOM_ICC_BIMC:
		return qcom_icc_set_bimc_qos(node, sum_bw);

	case QCOM_ICC_QNOC:
		return qcom_icc_set_qnoc_qos(node, sum_bw);
	default:
		return qcom_icc_set_noc_qos(node, sum_bw);
	}
}

static int qcom_icc_rpm_set(int mas_rpm_id, int slv_rpm_id, u64 sum_bw)
{
@@ -309,7 +341,7 @@ int qnoc_probe(struct platform_device *pdev)
		qp->bus_clks[i].id = cds[i];
	qp->num_clks = cd_num;

	qp->is_bimc_node = desc->is_bimc_node;
	qp->type = desc->type;
	qp->qos_offset = desc->qos_offset;

	if (desc->regmap_cfg) {
@@ -317,8 +349,13 @@ int qnoc_probe(struct platform_device *pdev)
		void __iomem *mmio;

		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
		if (!res)
		if (!res) {
			/* Try parent's regmap */
			qp->regmap = dev_get_regmap(dev->parent, NULL);
			if (qp->regmap)
				goto regmap_done;
			return -ENODEV;
		}

		mmio = devm_ioremap_resource(dev, res);

@@ -334,6 +371,7 @@ int qnoc_probe(struct platform_device *pdev)
		}
	}

regmap_done:
	ret = devm_clk_bulk_get(dev, qp->num_clks, qp->bus_clks);
	if (ret)
		return ret;
@@ -385,6 +423,10 @@ int qnoc_probe(struct platform_device *pdev)

	platform_set_drvdata(pdev, qp);

	/* Populate child NoC devices if any */
	if (of_get_child_count(dev->of_node) > 0)
		return of_platform_populate(dev->of_node, NULL, NULL, dev);

	return 0;
err:
	icc_nodes_remove(provider);
+11 −3
Original line number Diff line number Diff line
@@ -12,19 +12,25 @@
#define to_qcom_provider(_provider) \
	container_of(_provider, struct qcom_icc_provider, provider)

enum qcom_icc_type {
	QCOM_ICC_NOC,
	QCOM_ICC_BIMC,
	QCOM_ICC_QNOC,
};

/**
 * struct qcom_icc_provider - Qualcomm specific interconnect provider
 * @provider: generic interconnect provider
 * @bus_clks: the clk_bulk_data table of bus clocks
 * @num_clks: the total number of clk_bulk_data entries
 * @is_bimc_node: indicates whether to use bimc specific setting
 * @type: the ICC provider type
 * @qos_offset: offset to QoS registers
 * @regmap: regmap for QoS registers read/write access
 */
struct qcom_icc_provider {
	struct icc_provider provider;
	int num_clks;
	bool is_bimc_node;
	enum qcom_icc_type type;
	struct regmap *regmap;
	unsigned int qos_offset;
	struct clk_bulk_data bus_clks[];
@@ -38,6 +44,7 @@ struct qcom_icc_provider {
 * @ap_owned: indicates if the node is owned by the AP or by the RPM
 * @qos_mode: default qos mode for this node
 * @qos_port: qos port number for finding qos registers of this node
 * @urg_fwd_en: enable urgent forwarding
 */
struct qcom_icc_qos {
	u32 areq_prio;
@@ -46,6 +53,7 @@ struct qcom_icc_qos {
	bool ap_owned;
	int qos_mode;
	int qos_port;
	bool urg_fwd_en;
};

/**
@@ -78,7 +86,7 @@ struct qcom_icc_desc {
	const char * const *clocks;
	size_t num_clocks;
	bool has_bus_pd;
	bool is_bimc_node;
	enum qcom_icc_type type;
	const struct regmap_config *regmap_cfg;
	unsigned int qos_offset;
};
Loading