linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] SDM845 System Cache Driver
@ 2018-01-25 23:55 Channagoud Kadabi
  2018-01-25 23:55 ` [PATCH 1/2] dt-bindings: Documentation for qcom,llcc Channagoud Kadabi
  2018-01-25 23:55 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
  0 siblings, 2 replies; 20+ messages in thread
From: Channagoud Kadabi @ 2018-01-25 23:55 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm
  Cc: linux-arm, linux-kernel, tsoni, sboyd, kyan, Channagoud Kadabi

This series implements system cache or LLCC(Last Level Cache Controller) driver
for SDM845 SOC. The purpose of the driver is to partition the system cache and
program the settings such as priortiy, lines to probe while doing a look up
in the system cache, low power related settings etc. The partitions are called
cache slices. Each cache slice is associated with size and SCID (System Cache ID)
The driver also provides API for clients to query the cache slice details,
activate and deactivate them.

System cache has other blocks for memory error detection and
AMON (Activity Monitor) for lock up detection.

Since the hardware block has multiple functional units the driver is implemented
to use syscon/regmap interface. The driver can be broadly classified into:

- Core driver: llcc-core.c: This driver initializes the syscon, does common
settings required to enable interrupts and error handling features.

- SOC specific driver: llcc-sdm845.c: Cache partitioning and cache slice
properties for usecases on sdm845 that need to use system cache.

- API : llcc-slice.c: Exports APIs to clients to query cache slice details,
activate and deactivate cache slices.

Channagoud Kadabi (2):
  dt-bindings: Documentation for qcom,llcc
  drivers: soc: Add LLCC driver

 .../devicetree/bindings/arm/msm/qcom,llcc.txt      |  93 +++++
 drivers/soc/qcom/Kconfig                           |  16 +
 drivers/soc/qcom/Makefile                          |   2 +
 drivers/soc/qcom/llcc-core.c                       | 120 ++++++
 drivers/soc/qcom/llcc-sdm845.c                     | 102 +++++
 drivers/soc/qcom/llcc-slice.c                      | 456 +++++++++++++++++++++
 include/linux/soc/qcom/llcc-qcom.h                 | 152 +++++++
 7 files changed, 941 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
 create mode 100644 drivers/soc/qcom/llcc-core.c
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-01-25 23:55 [PATCH 0/2] SDM845 System Cache Driver Channagoud Kadabi
@ 2018-01-25 23:55 ` Channagoud Kadabi
  2018-02-01 10:44   ` Mark Rutland
                     ` (2 more replies)
  2018-01-25 23:55 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
  1 sibling, 3 replies; 20+ messages in thread
From: Channagoud Kadabi @ 2018-01-25 23:55 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm
  Cc: linux-arm, linux-kernel, tsoni, sboyd, kyan, Channagoud Kadabi

Documentation for last level cache controller device tree bindings,
client bindings usage examples.

Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
---
 .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93 ++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt

diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
new file mode 100644
index 0000000..d433b0c
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
@@ -0,0 +1,93 @@
+* LLCC (Last Level Cache Controller)
+
+Properties:
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,llcc-core"
+
+- reg:
+	Usage: required
+	Value Type: <prop-encoded-array>
+	Definition: must be addresses and sizes of the LLCC registers
+
+- llcc-bank-off:
+	Usage: required
+	Value Type: <u32 array>
+	Definition: Offsets of llcc banks from llcc base address starting from
+		    LLCC bank0.
+
+- llcc-broadcast-off:
+	Usage: required
+	Value Type: <u32>
+	Definition: Offset of broadcast register from LLCC bank0 address.
+
+- #cache-cells:
+	Usage: required
+	Value Type: <u32>
+	Definition: Number of cache cells, must be 1
+
+- max-slices:
+	usage: required
+	Value Type: <u32>
+	Definition: Number of cache slices supported by hardware
+
+- status:
+	Usage: optional
+	Value type: <string>
+	Definition: Property to enable or disable the driver
+
+== llcc amon device ==
+
+Properties:
+-qcom,fg-cnt : The value of fine grained counter of activity monitor
+	        block.
+
+compatible devices:
+		qcom,sdm845-llcc
+
+Example:
+
+	qcom,system-cache@1300000 {
+		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
+		reg = <0x1300000 0x50000>;
+		reg-names = "llcc_base";
+
+		llcc: qcom,sdm845-llcc {
+			compatible = "qcom,sdm845-llcc";
+			#cache-cells = <1>;
+			max-slices = <32>;
+		};
+
+		qcom,llcc-ecc {
+			compatible = "qcom,llcc-ecc";
+		};
+
+		qcom,llcc-amon {
+			compatible = "qcom,llcc-amon";
+			qcom,fg-cnt = <0x7>;
+		};
+
+	};
+
+== Client ==
+
+Properties:
+- cache-slice-names:
+	Usage: required
+	Value type: <stringlist>
+	Definition: A set of names that identify the usecase names of a client that uses
+		    cache slice. These strings are used to look up the cache slice
+		    entries by name.
+
+- cache-slices:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: The tuple has phandle to llcc device as the first argument and the
+		    second argument is the usecase id of the client.
+For example:
+
+	video-decoder-encoder {
+		cache-slice-names = "vidsc0", "vidsc1";
+		cache-slices = <&llcc 2>, <&llcc 3>;
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCH 2/2] drivers: soc: Add LLCC driver
  2018-01-25 23:55 [PATCH 0/2] SDM845 System Cache Driver Channagoud Kadabi
  2018-01-25 23:55 ` [PATCH 1/2] dt-bindings: Documentation for qcom,llcc Channagoud Kadabi
@ 2018-01-25 23:55 ` Channagoud Kadabi
  2018-03-19 14:55   ` Jordan Crouse
  1 sibling, 1 reply; 20+ messages in thread
From: Channagoud Kadabi @ 2018-01-25 23:55 UTC (permalink / raw)
  To: linux-arm-kernel, linux-arm-msm
  Cc: linux-arm, linux-kernel, tsoni, sboyd, kyan, Channagoud Kadabi

LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into muliple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice for their usecase and activate or deactivate the slice as needed.
LLCC driver provides API interfaces for the clients to perform these
operations.

Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
---
 drivers/soc/qcom/Kconfig           |  16 ++
 drivers/soc/qcom/Makefile          |   2 +
 drivers/soc/qcom/llcc-core.c       | 120 ++++++++++
 drivers/soc/qcom/llcc-sdm845.c     | 102 +++++++++
 drivers/soc/qcom/llcc-slice.c      | 456 +++++++++++++++++++++++++++++++++++++
 include/linux/soc/qcom/llcc-qcom.h | 152 +++++++++++++
 6 files changed, 848 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-core.c
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index b81374b..c9bfe44 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -89,6 +89,22 @@ config QCOM_SMSM
 	  Say yes here to support the Qualcomm Shared Memory State Machine.
 	  The state machine is represented by bits in shared memory.
 
+config QCOM_LLCC
+	tristate "Qualcomm Technologies, Inc. LLCC driver"
+	depends on ARCH_QCOM
+	help
+	  Qualcomm Technologies, Inc. platform specific LLCC driver for Last
+	  Level Cache. This provides interfaces to client's that use the LLCC.
+	  Say yes here to enable LLCC slice driver.
+
+config QCOM_SDM845_LLCC
+	tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+	depends on QCOM_LLCC
+	help
+	  Say yes here to enable the LLCC driver for SDM845. This is provides
+	  data required to configure LLCC so that clients can start using the
+	  LLCC slices.
+
 config QCOM_WCNSS_CTRL
 	tristate "Qualcomm WCNSS control driver"
 	depends on ARCH_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 40c56f6..2dc917e 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_QCOM_GLINK_SSR) +=	glink_ssr.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-core.o llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)	+= mdt_loader.o
 obj-$(CONFIG_QCOM_PM)	+=	spm.o
diff --git a/drivers/soc/qcom/llcc-core.c b/drivers/soc/qcom/llcc-core.c
new file mode 100644
index 0000000..53289bb
--- /dev/null
+++ b/drivers/soc/qcom/llcc-core.c
@@ -0,0 +1,120 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+/* Config registers offsets*/
+#define DRP_ECC_ERROR_CFG	0x00040000
+
+/* TRP, DRP interrupt register offsets */
+#define CMN_INTERRUPT_0_ENABLE		0x0003001C
+#define CMN_INTERRUPT_2_ENABLE		0x0003003C
+#define TRP_INTERRUPT_0_ENABLE		0x00020488
+#define DRP_INTERRUPT_ENABLE		0x0004100C
+
+#define SB_ERROR_THRESHOLD	0x1
+#define SB_ERROR_THRESHOLD_SHIFT	24
+#define SB_DB_TRP_INTERRUPT_ENABLE	0x3
+#define TRP0_INTERRUPT_ENABLE	0x1
+#define DRP0_INTERRUPT_ENABLE	BIT(6)
+#define SB_DB_DRP_INTERRUPT_ENABLE	0x3
+
+#ifdef CONFIG_EDAC_QCOM_LLCC
+#define ENABLE_ECC_INTR 1
+#else
+#define ENABLE_ECC_INTR 0
+#endif
+
+static int enable_ecc_intr = ENABLE_ECC_INTR;
+module_param(enable_ecc_intr, int, 0444);
+
+static void qcom_llcc_core_setup(struct regmap *llcc_regmap, uint32_t b_off)
+{
+	u32 sb_err_threshold;
+
+	/* Enable TRP in instance 2 of common interrupt enable register */
+	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
+			   TRP0_INTERRUPT_ENABLE, TRP0_INTERRUPT_ENABLE);
+
+	/* Enable ECC interrupts on Tag Ram */
+	regmap_update_bits(llcc_regmap, b_off + TRP_INTERRUPT_0_ENABLE,
+		SB_DB_TRP_INTERRUPT_ENABLE, SB_DB_TRP_INTERRUPT_ENABLE);
+
+	/* Enable SB error for Data RAM */
+	sb_err_threshold = (SB_ERROR_THRESHOLD << SB_ERROR_THRESHOLD_SHIFT);
+	regmap_write(llcc_regmap, b_off + DRP_ECC_ERROR_CFG, sb_err_threshold);
+
+	/* Enable DRP in instance 2 of common interrupt enable register */
+	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
+			   DRP0_INTERRUPT_ENABLE, DRP0_INTERRUPT_ENABLE);
+
+	/* Enable ECC interrupts on Data Ram */
+	regmap_write(llcc_regmap, b_off + DRP_INTERRUPT_ENABLE,
+		     SB_DB_DRP_INTERRUPT_ENABLE);
+}
+
+static int qcom_llcc_core_probe(struct platform_device *pdev)
+{
+	struct regmap *llcc_regmap;
+	struct device *dev = &pdev->dev;
+	u32 b_off = 0;
+	int ret = 0;
+
+	llcc_regmap = syscon_node_to_regmap(dev->of_node);
+
+	if (IS_ERR(llcc_regmap)) {
+		dev_err(&pdev->dev, "Cannot find regmap for llcc\n");
+		return PTR_ERR(llcc_regmap);
+	}
+
+	ret = of_property_read_u32(dev->of_node,
+			"qcom,llcc-broadcast-off", &b_off);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to read broadcast-off\n");
+		return -EINVAL;
+	}
+
+	if (enable_ecc_intr)
+		qcom_llcc_core_setup(llcc_regmap, b_off);
+
+	return 0;
+}
+
+static int qcom_llcc_core_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id qcom_llcc_core_match_table[] = {
+	{ .compatible = "qcom,llcc-core" },
+	{ },
+};
+
+static struct platform_driver qcom_llcc_core_driver = {
+	.probe = qcom_llcc_core_probe,
+	.remove = qcom_llcc_core_remove,
+	.driver = {
+		.name = "qcom_llcc_core",
+		.of_match_table = qcom_llcc_core_match_table,
+	},
+};
+module_platform_driver(qcom_llcc_core_driver);
+
+MODULE_DESCRIPTION("QCOM LLCC Core Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 0000000..74a63f77
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,102 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+/*
+ * SCT entry contains of the following parameters
+ * name: Name of the client's use case for which the llcc slice is used
+ * uid: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Determine of the slice has a fixed capacity
+ * bonus_ways: Bonus ways to be used by any slice, bonus way is used only if
+ *             it't not a reserved way.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot be used
+ *           by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ *             slice normal or TCM
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *                    configured to 1 only bonus and reseved ways are probed.
+ *                    when configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maitained active vote
+ *               then the ways assigned to this client are not flushed on power
+ *               collapse.
+ * activate_on_init: Activate the slice immidiately after the SCT is programmed
+ */
+#define SCT_ENTRY(n, uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+	{					\
+		.name = n,			\
+		.usecase_id = uid,		\
+		.slice_id = sid,		\
+		.max_cap = mc,			\
+		.priority = p,			\
+		.fixed_size = fs,		\
+		.bonus_ways = bway,		\
+		.res_ways = rway,		\
+		.cache_mode = cmod,		\
+		.probe_target_ways = ptw,	\
+		.dis_cap_alloc = dca,		\
+		.retain_on_pc = rp,		\
+		.activate_on_init = a,		\
+	}
+
+static struct llcc_slice_config sdm845_data[] =  {
+	SCT_ENTRY("cpuss",       1, 1, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 1),
+	SCT_ENTRY("vidsc0",      2, 2, 512, 2, 1, 0x0,  0x0F0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("vidsc1",      3, 3, 512, 2, 1, 0x0,  0x0F0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("rotator",     4, 4, 563, 2, 1, 0x0,  0x00e, 2, 0, 1, 1, 0),
+	SCT_ENTRY("voice",       5, 5, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("audio",       6, 6, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0x0FC, 0xF00, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modem",       8, 8, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("compute",     10, 10, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("gpuhtw",      11, 11, 512, 1, 1, 0xC,  0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("gpu",         12, 12, 2304, 1, 0, 0xFF0, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("mmuhwt",      13, 13, 256, 2, 0, 0x0,  0x1, 0, 0, 1, 0, 1),
+	SCT_ENTRY("compute_dma", 15, 15, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("display",     16, 16, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("videofw",     17, 17, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0x0,  0xF00, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("audiohw",     22, 22, 1024, 1, 1, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+};
+
+static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
+{
+	return qcom_llcc_probe(pdev, sdm845_data,
+				 ARRAY_SIZE(sdm845_data));
+}
+
+static const struct of_device_id sdm845_qcom_llcc_of_match[] = {
+	{ .compatible = "qcom,sdm845-llcc", },
+	{ },
+};
+
+static struct platform_driver sdm845_qcom_llcc_driver = {
+	.driver = {
+		.name = "sdm845-llcc",
+		.of_match_table = sdm845_qcom_llcc_of_match,
+	},
+	.probe = sdm845_qcom_llcc_probe,
+	.remove = qcom_llcc_remove,
+};
+module_platform_driver(sdm845_qcom_llcc_driver);
+
+MODULE_DESCRIPTION("QTI sdm845 LLCC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
new file mode 100644
index 0000000..e67a1ef
--- /dev/null
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -0,0 +1,456 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)  "%s:" fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+#define ACTIVATE                      0x1
+#define DEACTIVATE                    0x2
+#define ACT_CTRL_OPCODE_ACTIVATE      0x1
+#define ACT_CTRL_OPCODE_DEACTIVATE    0x2
+#define ACT_CTRL_ACT_TRIG             0x1
+#define ACT_CTRL_OPCODE_SHIFT         0x1
+#define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x2
+#define ATTR1_FIXED_SIZE_SHIFT        0x3
+#define ATTR1_PRIORITY_SHIFT          0x4
+#define ATTR1_MAX_CAP_SHIFT           0x10
+#define ATTR0_RES_WAYS_MASK           0x00000fff
+#define ATR0_BONUS_WAYS_MASK          0x0fff0000
+#define ATR0_BONUS_WAYS_SHIFT         0x10
+#define LLCC_STATUS_READ_DELAY 100
+
+#define CACHE_LINE_SIZE_SHIFT 6
+
+#define LLCC_COMMON_STATUS0		0x0003000C
+#define LLCC_LB_CNT_MASK		0xf0000000
+#define LLCC_LB_CNT_SHIFT		28
+
+#define MAX_CAP_TO_BYTES(n) (n * 1024)
+#define LLCC_TRP_ACT_CTRLn(n) (n * 0x1000)
+#define LLCC_TRP_STATUSn(n)   (4 + n * 0x1000)
+#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + 0x8 * n)
+#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + 0x8 * n)
+
+/**
+ * Driver data for llcc
+ * @llcc_virt_base: base address for llcc controller
+ * @slice_data: pointer to llcc slice config data
+ * @sz: Size of the config data table
+ * @llcc_slice_map: Bit map to track the active slice ids
+ */
+struct llcc_drv_data {
+	struct regmap *llcc_map;
+	const struct llcc_slice_config *slice_data;
+	struct mutex slice_mutex;
+	u32 llcc_config_data_sz;
+	u32 max_slices;
+	u32 b_off;
+	u32 no_banks;
+	unsigned long *llcc_slice_map;
+};
+
+/* Get the slice entry by index */
+static struct llcc_slice_desc *llcc_slice_get_entry(struct device *dev, int n)
+{
+	struct of_phandle_args phargs;
+	struct llcc_drv_data *drv;
+	const struct llcc_slice_config *llcc_data_ptr;
+	struct llcc_slice_desc *desc;
+	struct platform_device *pdev;
+	u32 sz, count;
+
+	if (of_parse_phandle_with_args(dev->of_node, "cache-slices",
+				       "#cache-cells", n, &phargs)) {
+		pr_err("can't parse \"cache-slices\" property\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	pdev = of_find_device_by_node(phargs.np);
+	if (!pdev) {
+		pr_err("Cannot find platform device from phandle\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	drv = platform_get_drvdata(pdev);
+	if (!drv) {
+		pr_err("cannot find platform driver data\n");
+		return ERR_PTR(-EFAULT);
+	}
+
+	llcc_data_ptr = drv->slice_data;
+	sz = drv->llcc_config_data_sz;
+	count = 0;
+
+	while (llcc_data_ptr && count < sz) {
+		if (llcc_data_ptr->usecase_id == phargs.args[0])
+			break;
+		llcc_data_ptr++;
+		count++;
+	}
+
+	if (llcc_data_ptr == NULL || count == sz) {
+		pr_err("can't find %d usecase id\n", phargs.args[0]);
+		return ERR_PTR(-ENODEV);
+	}
+
+	desc = kzalloc(sizeof(struct llcc_slice_desc), GFP_KERNEL);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->llcc_slice_id = llcc_data_ptr->slice_id;
+	desc->llcc_slice_size = llcc_data_ptr->max_cap;
+	desc->dev = &pdev->dev;
+
+	return desc;
+}
+
+/**
+ * llcc_slice_getd - get llcc slice descriptor
+ * @dev: Device pointer of the client
+ * @name: Name of the use case
+ *
+ * A pointer to llcc slice descriptor will be returned on success and
+ * and error pointer is returned on failure
+ */
+struct llcc_slice_desc *llcc_slice_getd(struct device *dev, const char *name)
+{
+	struct device_node *np = dev->of_node;
+	int index = 0;
+	const char *slice_name;
+	struct property *prop;
+
+	if (!np) {
+		dev_err(dev, "%s() currently only supports DT\n", __func__);
+		return ERR_PTR(-ENOENT);
+	}
+
+	if (!of_get_property(np, "cache-slice-names", NULL)) {
+		dev_err(dev,
+			"%s() requires a \"cache-slice-names\" property\n",
+			__func__);
+		return ERR_PTR(-ENOENT);
+	}
+
+	of_property_for_each_string(np, "cache-slice-names", prop, slice_name) {
+		if (!strcmp(name, slice_name))
+			break;
+		index++;
+	}
+
+	return llcc_slice_get_entry(dev, index);
+}
+EXPORT_SYMBOL(llcc_slice_getd);
+
+/**
+ * llcc_slice_putd - llcc slice descritpor
+ * @desc: Pointer to llcc slice descriptor
+ */
+void llcc_slice_putd(struct llcc_slice_desc *desc)
+{
+	kfree(desc);
+}
+EXPORT_SYMBOL(llcc_slice_putd);
+
+static int llcc_update_act_ctrl(struct llcc_drv_data *drv, u32 sid,
+				u32 act_ctrl_reg_val, u32 status)
+{
+	u32 act_ctrl_reg;
+	u32 status_reg;
+	u32 slice_status;
+	unsigned long timeout;
+
+	act_ctrl_reg = drv->b_off + LLCC_TRP_ACT_CTRLn(sid);
+	status_reg = drv->b_off + LLCC_TRP_STATUSn(sid);
+
+	regmap_write(drv->llcc_map, act_ctrl_reg, act_ctrl_reg_val);
+
+	/* Make sure the activate trigger is applied before clearing it */
+	mb();
+
+	/* Clear the ACTIVE trigger */
+	act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
+	regmap_write(drv->llcc_map, act_ctrl_reg, act_ctrl_reg_val);
+
+	timeout = jiffies + usecs_to_jiffies(LLCC_STATUS_READ_DELAY);
+	while (time_before(jiffies, timeout)) {
+		regmap_read(drv->llcc_map, status_reg, &slice_status);
+		if (!(slice_status & status))
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * llcc_slice_activate - Activate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A value zero will be returned on success and a negative errno will
+ * be returned in error cases
+ */
+int llcc_slice_activate(struct llcc_slice_desc *desc)
+{
+	int rc = -EINVAL;
+	u32 act_ctrl_val;
+	struct llcc_drv_data *drv;
+
+	if (desc == NULL) {
+		pr_err("Input descriptor supplied is invalid\n");
+		return rc;
+	}
+
+	drv = dev_get_drvdata(desc->dev);
+	if (!drv) {
+		pr_err("Invalid device pointer in the desc\n");
+		return rc;
+	}
+
+	mutex_lock(&drv->slice_mutex);
+	if (test_bit(desc->llcc_slice_id, drv->llcc_slice_map)) {
+		mutex_unlock(&drv->slice_mutex);
+		return 0;
+	}
+
+	act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT;
+	act_ctrl_val |= ACT_CTRL_ACT_TRIG;
+
+	rc = llcc_update_act_ctrl(drv, desc->llcc_slice_id, act_ctrl_val,
+				  DEACTIVATE);
+
+	__set_bit(desc->llcc_slice_id, drv->llcc_slice_map);
+	mutex_unlock(&drv->slice_mutex);
+
+	return rc;
+}
+EXPORT_SYMBOL(llcc_slice_activate);
+
+/**
+ * llcc_slice_deactivate - Deactivate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A value zero will be returned on success and a negative errno will
+ * be returned in error cases
+ */
+int llcc_slice_deactivate(struct llcc_slice_desc *desc)
+{
+	u32 act_ctrl_val;
+	int rc = -EINVAL;
+	struct llcc_drv_data *drv;
+
+	if (desc == NULL) {
+		pr_err("Input descriptor supplied is invalid\n");
+		return rc;
+	}
+
+	drv = dev_get_drvdata(desc->dev);
+	if (!drv) {
+		pr_err("Invalid device pointer in the desc\n");
+		return rc;
+	}
+
+	mutex_lock(&drv->slice_mutex);
+	if (!test_bit(desc->llcc_slice_id, drv->llcc_slice_map)) {
+		mutex_unlock(&drv->slice_mutex);
+		return 0;
+	}
+	act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
+	act_ctrl_val |= ACT_CTRL_ACT_TRIG;
+
+	rc = llcc_update_act_ctrl(drv, desc->llcc_slice_id, act_ctrl_val,
+				  ACTIVATE);
+
+	__clear_bit(desc->llcc_slice_id, drv->llcc_slice_map);
+	mutex_unlock(&drv->slice_mutex);
+
+	return rc;
+}
+EXPORT_SYMBOL(llcc_slice_deactivate);
+
+/**
+ * llcc_get_slice_id - return the slice id
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A positive value will be returned on success and a negative errno will
+ * be returned on error
+ */
+int llcc_get_slice_id(struct llcc_slice_desc *desc)
+{
+	if (!desc)
+		return -EINVAL;
+
+	return desc->llcc_slice_id;
+}
+EXPORT_SYMBOL(llcc_get_slice_id);
+
+/**
+ * llcc_get_slice_size - return the slice id
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A positive value will be returned on success and zero will returned on
+ * error
+ */
+size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
+{
+	if (!desc)
+		return 0;
+
+	return desc->llcc_slice_size;
+}
+EXPORT_SYMBOL(llcc_get_slice_size);
+
+static void qcom_llcc_cfg_program(struct platform_device *pdev)
+{
+	int i;
+	u32 attr1_cfg;
+	u32 attr0_cfg;
+	u32 attr1_val;
+	u32 attr0_val;
+	u32 max_cap_cacheline;
+	u32 sz;
+	const struct llcc_slice_config *llcc_table;
+	struct llcc_drv_data *drv = platform_get_drvdata(pdev);
+	struct llcc_slice_desc desc;
+	u32 b_off = drv->b_off;
+
+	sz = drv->llcc_config_data_sz;
+	llcc_table = drv->slice_data;
+
+	for (i = 0; i < sz; i++) {
+		attr1_cfg = b_off + LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
+		attr0_cfg = b_off + LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
+
+		attr1_val = llcc_table[i].cache_mode;
+		attr1_val |= (llcc_table[i].probe_target_ways <<
+				ATTR1_PROBE_TARGET_WAYS_SHIFT);
+		attr1_val |= (llcc_table[i].fixed_size <<
+				ATTR1_FIXED_SIZE_SHIFT);
+		attr1_val |= (llcc_table[i].priority << ATTR1_PRIORITY_SHIFT);
+
+		max_cap_cacheline = MAX_CAP_TO_BYTES(llcc_table[i].max_cap);
+
+		/* LLCC instances can vary for each target.
+		 * The SW writes to broadcast register which gets propagated
+		 * to each llcc instace (llcc0,.. llccN).
+		 * Since the size of the memory is divided equally amongst the
+		 * llcc instances, we need to configure the max cap accordingly.
+		 */
+		max_cap_cacheline = (max_cap_cacheline / drv->no_banks);
+		max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
+		attr1_val |= (max_cap_cacheline << ATTR1_MAX_CAP_SHIFT);
+
+		attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
+		attr0_val |= llcc_table[i].bonus_ways << ATR0_BONUS_WAYS_SHIFT;
+
+		regmap_write(drv->llcc_map, attr1_cfg, attr1_val);
+		regmap_write(drv->llcc_map, attr0_cfg, attr0_val);
+
+		/* Make sure that the SCT is programmed before activating */
+		mb();
+
+		if (llcc_table[i].activate_on_init) {
+			desc.llcc_slice_id = llcc_table[i].slice_id;
+			desc.dev = &pdev->dev;
+			if (llcc_slice_activate(&desc)) {
+				pr_err("activate slice id: %d timed out\n",
+						desc.llcc_slice_id);
+			}
+		}
+	}
+}
+
+int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *llcc_cfg, u32 sz)
+{
+	int rc = 0;
+	u32 num_banks = 0;
+	struct device *dev = &pdev->dev;
+	static struct llcc_drv_data *drv_data;
+
+	drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return PTR_ERR(drv_data);
+
+	drv_data->llcc_map = syscon_node_to_regmap(dev->parent->of_node);
+	if (!drv_data->llcc_map)
+		return PTR_ERR(drv_data->llcc_map);
+
+	regmap_read(drv_data->llcc_map, LLCC_COMMON_STATUS0,
+		    &num_banks);
+
+	num_banks &= LLCC_LB_CNT_MASK;
+	num_banks >>= LLCC_LB_CNT_SHIFT;
+	drv_data->no_banks = num_banks;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "max-slices",
+				  &drv_data->max_slices);
+	if (rc) {
+		dev_err(&pdev->dev, "Invalid max-slices dt entry\n");
+		devm_kfree(&pdev->dev, drv_data);
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.parent->of_node,
+			"qcom,llcc-broadcast-off", &drv_data->b_off);
+	if (rc) {
+		dev_err(&pdev->dev, "Invalid qcom,broadcast-off entry\n");
+		devm_kfree(&pdev->dev, drv_data);
+		return rc;
+	}
+
+	drv_data->llcc_slice_map = kcalloc(BITS_TO_LONGS(drv_data->max_slices),
+				   sizeof(unsigned long), GFP_KERNEL);
+
+	if (!drv_data->llcc_slice_map) {
+		devm_kfree(&pdev->dev, drv_data);
+		return PTR_ERR(drv_data->llcc_slice_map);
+	}
+
+	bitmap_zero(drv_data->llcc_slice_map, drv_data->max_slices);
+	drv_data->slice_data = llcc_cfg;
+	drv_data->llcc_config_data_sz = sz;
+	mutex_init(&drv_data->slice_mutex);
+	platform_set_drvdata(pdev, drv_data);
+
+	qcom_llcc_cfg_program(pdev);
+
+	return rc;
+}
+EXPORT_SYMBOL(qcom_llcc_probe);
+
+int qcom_llcc_remove(struct platform_device *pdev)
+{
+	static struct llcc_drv_data *drv_data;
+
+	drv_data = platform_get_drvdata(pdev);
+
+	mutex_destroy(&drv_data->slice_mutex);
+	kfree(drv_data->llcc_slice_map);
+	devm_kfree(&pdev->dev, drv_data);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_llcc_remove);
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
new file mode 100644
index 0000000..14bd7e7
--- /dev/null
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -0,0 +1,152 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LLCC_QCOM__
+#define __LLCC_QCOM__
+
+/**
+ * llcc_slice_desc - Cache slice descriptor
+ * @llcc_slice_id: llcc slice id
+ * @llcc_slice_size: Size allocated for the llcc slice
+ * @dev: pointer to llcc device
+ */
+struct llcc_slice_desc {
+	int llcc_slice_id;
+	size_t llcc_slice_size;
+	struct device *dev;
+};
+
+/**
+ * llcc_slice_config - Data associated with the llcc slice
+ * @name: name of the use case associated with the llcc slice
+ * @usecase_id: usecase id for which the llcc slice is used
+ * @slice_id: llcc slice id assigned to each slice
+ * @max_cap: maximum capacity of the llcc slice
+ * @priority: priority of the llcc slice
+ * @fixed_size: whether the llcc slice can grow beyond its size
+ * @bonus_ways: bonus ways associated with llcc slice
+ * @res_ways: reserved ways associated with llcc slice
+ * @cache_mode: mode of the llcce slice
+ * @probe_target_ways: Probe only reserved and bonus ways on a cache miss
+ * @dis_cap_alloc: Disable capacity based allocation
+ * @retain_on_pc: Retain through power collapse
+ * @activate_on_init: activate the slice on init
+ */
+struct llcc_slice_config {
+	const char *name;
+	int usecase_id;
+	int slice_id;
+	u32 max_cap;
+	u32 priority;
+	bool fixed_size;
+	u32 bonus_ways;
+	u32 res_ways;
+	u32 cache_mode;
+	u32 probe_target_ways;
+	bool dis_cap_alloc;
+	bool retain_on_pc;
+	u32 activate_on_init;
+};
+
+#ifdef CONFIG_QCOM_LLCC
+/**
+ * llcc_slice_getd - get llcc slice descriptor
+ * @dev: Device pointer of the client
+ * @name: Name of the use case
+ */
+struct llcc_slice_desc *llcc_slice_getd(struct device *dev, const char *name);
+
+/**
+ * llcc_slice_putd - llcc slice descritpor
+ * @desc: Pointer to llcc slice descriptor
+ */
+void llcc_slice_putd(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_get_slice_id - get slice id
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_get_slice_id(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_get_slice_size - llcc slice size
+ * @desc: Pointer to llcc slice descriptor
+ */
+size_t llcc_get_slice_size(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_slice_activate - Activate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_slice_activate(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_slice_deactivate - Deactivate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_slice_deactivate(struct llcc_slice_desc *desc);
+
+/**
+ * qcom_llcc_probe - program the sct table
+ * @pdev: platform device pointer
+ * @table: soc sct table
+ */
+int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *table, u32 sz);
+/**
+ * qcom_llcc_remove - clean up llcc driver
+ * @pdev: platform driver pointer
+ */
+int qcom_llcc_remove(struct platform_device *pdev);
+#else
+static inline struct llcc_slice_desc *llcc_slice_getd(struct device *dev,
+			const char *name)
+{
+	return NULL;
+}
+
+static inline void llcc_slice_putd(struct llcc_slice_desc *desc)
+{
+
+};
+
+static inline int llcc_get_slice_id(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+
+static inline size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
+{
+	return 0;
+}
+static inline int llcc_slice_activate(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+
+static inline int llcc_slice_deactivate(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+static inline int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *table, u32 sz)
+{
+	return -ENODEV;
+}
+
+static inline int qcom_llcc_remove(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-01-25 23:55 ` [PATCH 1/2] dt-bindings: Documentation for qcom,llcc Channagoud Kadabi
@ 2018-02-01 10:44   ` Mark Rutland
  2018-02-01 20:39     ` Channa
  2018-02-01 10:48   ` Mark Rutland
  2018-02-08 16:52   ` Matt Sealey
  2 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2018-02-01 10:44 UTC (permalink / raw)
  To: Channagoud Kadabi
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
> Documentation for last level cache controller device tree bindings,
> client bindings usage examples.
> 
> Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
> ---
>  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93 ++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> 
> diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> new file mode 100644
> index 0000000..d433b0c
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> @@ -0,0 +1,93 @@
> +* LLCC (Last Level Cache Controller)
> +
> +Properties:
> +- compatible:
> +	Usage: required
> +	Value type: <string>
> +	Definition: must be "qcom,llcc-core"
> +
> +- reg:
> +	Usage: required
> +	Value Type: <prop-encoded-array>
> +	Definition: must be addresses and sizes of the LLCC registers
> +
> +- llcc-bank-off:
> +	Usage: required
> +	Value Type: <u32 array>
> +	Definition: Offsets of llcc banks from llcc base address starting from
> +		    LLCC bank0.
> +
> +- llcc-broadcast-off:
> +	Usage: required
> +	Value Type: <u32>
> +	Definition: Offset of broadcast register from LLCC bank0 address.

Please could we use "offset" rather than "off" for both of these? That
way it's obvious these aren't properties for disabling some feature.

How variable are these offsets in practice? Is the memory map not fixed?

> +
> +- #cache-cells:
> +	Usage: required
> +	Value Type: <u32>
> +	Definition: Number of cache cells, must be 1

What's this for, and how is it used?

> +
> +- max-slices:
> +	usage: required
> +	Value Type: <u32>
> +	Definition: Number of cache slices supported by hardware
> +
> +- status:
> +	Usage: optional
> +	Value type: <string>
> +	Definition: Property to enable or disable the driver

This is a standard property, so I don't think it needs to be described
here.

> +
> +== llcc amon device ==
> +
> +Properties:
> +-qcom,fg-cnt : The value of fine grained counter of activity monitor
> +	        block.

Could you elaborate on this?

> +
> +compatible devices:
> +		qcom,sdm845-llcc

Huh? The "qcom,sdm845-llcc" bindings wasn't described above, and it's
not clear what this means.

> +
> +Example:
> +
> +	qcom,system-cache@1300000 {
> +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";

This looks very wrong. Why do you need syscon and simple-mfd?

> +		reg = <0x1300000 0x50000>;
> +		reg-names = "llcc_base";
> +
> +		llcc: qcom,sdm845-llcc {
> +			compatible = "qcom,sdm845-llcc";

Why is this a sub-node?

Why isn't the top-level node just "qcom,sdm845-llcc" ?

> +			#cache-cells = <1>;
> +			max-slices = <32>;
> +		};
> +
> +		qcom,llcc-ecc {
> +			compatible = "qcom,llcc-ecc";
> +		};
> +
> +		qcom,llcc-amon {
> +			compatible = "qcom,llcc-amon";
> +			qcom,fg-cnt = <0x7>;
> +		};
> +
> +	};
> +
> +== Client ==
> +
> +Properties:
> +- cache-slice-names:
> +	Usage: required
> +	Value type: <stringlist>
> +	Definition: A set of names that identify the usecase names of a client that uses
> +		    cache slice. These strings are used to look up the cache slice
> +		    entries by name.
> +
> +- cache-slices:
> +	Usage: required
> +	Value type: <prop-encoded-array>
> +	Definition: The tuple has phandle to llcc device as the first argument and the
> +		    second argument is the usecase id of the client.

What is a "usecase id" ?

Is this meant to align with #cache-cells? It would be best to keep a
common prefix (i.e. call that #cache-slice-cells).

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-01-25 23:55 ` [PATCH 1/2] dt-bindings: Documentation for qcom,llcc Channagoud Kadabi
  2018-02-01 10:44   ` Mark Rutland
@ 2018-02-01 10:48   ` Mark Rutland
  2018-02-01 20:47     ` Channa
  2018-02-08 16:52   ` Matt Sealey
  2 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2018-02-01 10:48 UTC (permalink / raw)
  To: Channagoud Kadabi
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
> Documentation for last level cache controller device tree bindings,
> client bindings usage examples.
> 
> Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
> ---
>  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93 ++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> 
> +Example:
> +
> +	qcom,system-cache@1300000 {
> +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
> +		reg = <0x1300000 0x50000>;
> +		reg-names = "llcc_base";
> +
> +		llcc: qcom,sdm845-llcc {
> +			compatible = "qcom,sdm845-llcc";
> +			#cache-cells = <1>;
> +			max-slices = <32>;
> +		};
> +
> +		qcom,llcc-ecc {
> +			compatible = "qcom,llcc-ecc";
> +		};
> +
> +		qcom,llcc-amon {
> +			compatible = "qcom,llcc-amon";
> +			qcom,fg-cnt = <0x7>;
> +		};
> +
> +	};

The "qcom,llcc-ecc" and "qcom,llcc-amon" bindings doesn't seem to be
used by the driver in patch 2, and it's not clear how they are intended
to be used, so I think they should go from the binding for now.

I don't think you need syscon and simple-mfd, and I think you can
simplify the binding to a single node like:

	qcom,system-cache@1300000 {
		compatible = "qcom,sdm845-llcc";
		reg = <0x1300000 0x50000>;
		#cache-slice-cells = <1>;
		max-slices = <32>;
	}

If ECC and AMON are option features, we can always add boolean
properties for those later, e.g. "has-ecc".

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-01 10:44   ` Mark Rutland
@ 2018-02-01 20:39     ` Channa
  2018-02-02 11:05       ` Mark Rutland
  0 siblings, 1 reply; 20+ messages in thread
From: Channa @ 2018-02-01 20:39 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On 2018-02-01 02:44, Mark Rutland wrote:
> On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
>> Documentation for last level cache controller device tree bindings,
>> client bindings usage examples.
>> 
>> Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
>> ---
>>  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93 
>> ++++++++++++++++++++++
>>  1 file changed, 93 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> 
>> diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt 
>> b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> new file mode 100644
>> index 0000000..d433b0c
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> @@ -0,0 +1,93 @@
>> +* LLCC (Last Level Cache Controller)
>> +
>> +Properties:
>> +- compatible:
>> +	Usage: required
>> +	Value type: <string>
>> +	Definition: must be "qcom,llcc-core"
>> +
>> +- reg:
>> +	Usage: required
>> +	Value Type: <prop-encoded-array>
>> +	Definition: must be addresses and sizes of the LLCC registers
>> +
>> +- llcc-bank-off:
>> +	Usage: required
>> +	Value Type: <u32 array>
>> +	Definition: Offsets of llcc banks from llcc base address starting 
>> from
>> +		    LLCC bank0.
>> +
>> +- llcc-broadcast-off:
>> +	Usage: required
>> +	Value Type: <u32>
>> +	Definition: Offset of broadcast register from LLCC bank0 address.
> 
> Please could we use "offset" rather than "off" for both of these? That
> way it's obvious these aren't properties for disabling some feature.
> 
> How variable are these offsets in practice? Is the memory map not 
> fixed?

The offsets depends on the number of LLCC HW blocks. These number of HW 
blocks vary from
chipset to chipset and new registers could be added that changes the 
offset.

> 
>> +
>> +- #cache-cells:
>> +	Usage: required
>> +	Value Type: <u32>
>> +	Definition: Number of cache cells, must be 1
> 
> What's this for, and how is it used?

This is to obtain the phandle arguments from client devices. Related to 
cache-slices property.

> 
>> +
>> +- max-slices:
>> +	usage: required
>> +	Value Type: <u32>
>> +	Definition: Number of cache slices supported by hardware
>> +
>> +- status:
>> +	Usage: optional
>> +	Value type: <string>
>> +	Definition: Property to enable or disable the driver
> 
> This is a standard property, so I don't think it needs to be described
> here.

Sure, will remove it.

> 
>> +
>> +== llcc amon device ==
>> +
>> +Properties:
>> +-qcom,fg-cnt : The value of fine grained counter of activity monitor
>> +	        block.
> 
> Could you elaborate on this?

This is counter value programmed in the HW to detect live locks.
This parameter is tunable to avoid false positives.

> 
>> +
>> +compatible devices:
>> +		qcom,sdm845-llcc
> 
> Huh? The "qcom,sdm845-llcc" bindings wasn't described above, and it's
> not clear what this means.
> 
>> +
>> +Example:
>> +
>> +	qcom,system-cache@1300000 {
>> +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
> 
> This looks very wrong. Why do you need syscon and simple-mfd?

LLCC HW block has 3 functionalities:
System cache core, ECC & AMON drivers for debugging.
All three drivers use the same register space for configuration, status 
etc.
In order to avoid remapping the same address region across multiple 
drivers,
I have implemented this driver as a syncon and simple-mfd.

> 
>> +		reg = <0x1300000 0x50000>;
>> +		reg-names = "llcc_base";
>> +
>> +		llcc: qcom,sdm845-llcc {
>> +			compatible = "qcom,sdm845-llcc";
> 
> Why is this a sub-node?
qcom,sdm845-llcc: This core driver as mentioned in the list above.
> 
> Why isn't the top-level node just "qcom,sdm845-llcc" ?
> 
>> +			#cache-cells = <1>;
>> +			max-slices = <32>;
>> +		};
>> +
>> +		qcom,llcc-ecc {
>> +			compatible = "qcom,llcc-ecc";
>> +		};

qcom,llcc-ecc: Driver #2 for ECC

>> +
>> +		qcom,llcc-amon {
>> +			compatible = "qcom,llcc-amon";
>> +			qcom,fg-cnt = <0x7>;
>> +		};
>> +

qcom,llcc-amon: Driver #3 for AMON

>> +	};
>> +
>> +== Client ==
>> +
>> +Properties:
>> +- cache-slice-names:
>> +	Usage: required
>> +	Value type: <stringlist>
>> +	Definition: A set of names that identify the usecase names of a 
>> client that uses
>> +		    cache slice. These strings are used to look up the cache slice
>> +		    entries by name.
>> +
>> +- cache-slices:
>> +	Usage: required
>> +	Value type: <prop-encoded-array>
>> +	Definition: The tuple has phandle to llcc device as the first 
>> argument and the
>> +		    second argument is the usecase id of the client.
> 
> What is a "usecase id" ?

Usecase id for use case that wants to use system cache for eg: 
video-encode and video-decode

> 
> Is this meant to align with #cache-cells? It would be best to keep a
> common prefix (i.e. call that #cache-slice-cells).

Yes. Will update the name.

> 
> Thanks,
> Mark.

-- 
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-01 10:48   ` Mark Rutland
@ 2018-02-01 20:47     ` Channa
  2018-02-02 11:08       ` Mark Rutland
  0 siblings, 1 reply; 20+ messages in thread
From: Channa @ 2018-02-01 20:47 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan, linux-kernel-owner

On 2018-02-01 02:48, Mark Rutland wrote:
> On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
>> Documentation for last level cache controller device tree bindings,
>> client bindings usage examples.
>> 
>> Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
>> ---
>>  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93 
>> ++++++++++++++++++++++
>>  1 file changed, 93 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> 
>> +Example:
>> +
>> +	qcom,system-cache@1300000 {
>> +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
>> +		reg = <0x1300000 0x50000>;
>> +		reg-names = "llcc_base";
>> +
>> +		llcc: qcom,sdm845-llcc {
>> +			compatible = "qcom,sdm845-llcc";
>> +			#cache-cells = <1>;
>> +			max-slices = <32>;
>> +		};
>> +
>> +		qcom,llcc-ecc {
>> +			compatible = "qcom,llcc-ecc";
>> +		};
>> +
>> +		qcom,llcc-amon {
>> +			compatible = "qcom,llcc-amon";
>> +			qcom,fg-cnt = <0x7>;
>> +		};
>> +
>> +	};
> 
> The "qcom,llcc-ecc" and "qcom,llcc-amon" bindings doesn't seem to be
> used by the driver in patch 2, and it's not clear how they are intended
> to be used, so I think they should go from the binding for now.

Sure I can remove them for now and add them when the I push other 
drivers
for review.

> 
> I don't think you need syscon and simple-mfd, and I think you can

I used syscon and simple-mfd because three drivers touch the same 
address space.

Driver 1:
system cache core: The purpose of the driver is to partition the system 
cache
and program the settings such as priority, lines to probe while doing a 
look up
in the system cache, low power related settings etc.
The driver also provides API for clients to query the cache slice 
details,
activate and deactivate them.

Driver 2:
ECC to detect single and double bit errors in LLCC memory.
Implemented using EDAC framework.

Driver 3:
AMON: Activity Monitor to detect live lock ups in the HW block.
Implemented as SOC driver similar to driver #1.

Since the hardware block has multiple functional units the driver is 
implemented
to use syscon/regmap interface.

> simplify the binding to a single node like:
> 
> 	qcom,system-cache@1300000 {
> 		compatible = "qcom,sdm845-llcc";
> 		reg = <0x1300000 0x50000>;
> 		#cache-slice-cells = <1>;
> 		max-slices = <32>;
> 	}
> 
> If ECC and AMON are option features, we can always add boolean
> properties for those later, e.g. "has-ecc".
> 
> Thanks,
> Mark.

-- 
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-01 20:39     ` Channa
@ 2018-02-02 11:05       ` Mark Rutland
  2018-02-06 19:56         ` Channa
  0 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2018-02-02 11:05 UTC (permalink / raw)
  To: Channa
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On Thu, Feb 01, 2018 at 12:39:09PM -0800, Channa wrote:
> On 2018-02-01 02:44, Mark Rutland wrote:
> > On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
> > > Documentation for last level cache controller device tree bindings,
> > > client bindings usage examples.
> > > 
> > > Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
> > > ---
> > >  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93
> > > ++++++++++++++++++++++
> > >  1 file changed, 93 insertions(+)
> > >  create mode 100644
> > > Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> > > 
> > > diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> > > b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> > > new file mode 100644
> > > index 0000000..d433b0c
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> > > @@ -0,0 +1,93 @@
> > > +* LLCC (Last Level Cache Controller)
> > > +
> > > +Properties:
> > > +- compatible:
> > > +	Usage: required
> > > +	Value type: <string>
> > > +	Definition: must be "qcom,llcc-core"
> > > +
> > > +- reg:
> > > +	Usage: required
> > > +	Value Type: <prop-encoded-array>
> > > +	Definition: must be addresses and sizes of the LLCC registers
> > > +
> > > +- llcc-bank-off:
> > > +	Usage: required
> > > +	Value Type: <u32 array>
> > > +	Definition: Offsets of llcc banks from llcc base address starting
> > > from
> > > +		    LLCC bank0.
> > > +
> > > +- llcc-broadcast-off:
> > > +	Usage: required
> > > +	Value Type: <u32>
> > > +	Definition: Offset of broadcast register from LLCC bank0 address.
> > 
> > Please could we use "offset" rather than "off" for both of these? That
> > way it's obvious these aren't properties for disabling some feature.
> > 
> > How variable are these offsets in practice? Is the memory map not fixed?
> 
> The offsets depends on the number of LLCC HW blocks. These number of HW
> blocks vary from
> chipset to chipset and new registers could be added that changes the offset.

Surely if new registers are added, we need a new compatible string?

Can't we encode the number of LLCC HW blocks, instead? Presumably that
would give enough information to cover both llcc-bank-off and
llcc-broadcast-off.

[...]

> > > +
> > > +compatible devices:
> > > +		qcom,sdm845-llcc
> > 
> > Huh? The "qcom,sdm845-llcc" bindings wasn't described above, and it's
> > not clear what this means.
> > 
> > > +
> > > +Example:
> > > +
> > > +	qcom,system-cache@1300000 {
> > > +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
> > 
> > This looks very wrong. Why do you need syscon and simple-mfd?
> 
> LLCC HW block has 3 functionalities:
> System cache core, ECC & AMON drivers for debugging.
> All three drivers use the same register space for configuration, status etc.
> In order to avoid remapping the same address region across multiple drivers,
> I have implemented this driver as a syncon and simple-mfd.

Please don't do that; that's completely dependent on Linux
implementation details.

Have one top level driver for the whole LLCC block, which maps the
registers, and provides an API for accessing them. When that probes, it
can cause the other drivers to be probed (e.g. with a platform device),
and those can access the LLCC registers via that API.

> > > +		reg = <0x1300000 0x50000>;
> > > +		reg-names = "llcc_base";
> > > +
> > > +		llcc: qcom,sdm845-llcc {
> > > +			compatible = "qcom,sdm845-llcc";
> > 
> > Why is this a sub-node?
> qcom,sdm845-llcc: This core driver as mentioned in the list above.
> > 
> > Why isn't the top-level node just "qcom,sdm845-llcc" ?
> > 
> > > +			#cache-cells = <1>;
> > > +			max-slices = <32>;
> > > +		};
> > > +
> > > +		qcom,llcc-ecc {
> > > +			compatible = "qcom,llcc-ecc";
> > > +		};
> 
> qcom,llcc-ecc: Driver #2 for ECC
> 
> > > +
> > > +		qcom,llcc-amon {
> > > +			compatible = "qcom,llcc-amon";
> > > +			qcom,fg-cnt = <0x7>;
> > > +		};
> > > +
> 
> qcom,llcc-amon: Driver #3 for AMON

Please describe the HW, not the drivers.

As above, I don't believe you need multiple nodes here. Linux can
instantiate the drivers as necessary.

[...]

> > > +- cache-slices:
> > > +	Usage: required
> > > +	Value type: <prop-encoded-array>
> > > +	Definition: The tuple has phandle to llcc device as the first
> > > argument and the
> > > +		    second argument is the usecase id of the client.
> > 
> > What is a "usecase id" ?
> 
> Usecase id for use case that wants to use system cache for eg: video-encode
> and video-decode

Sure, but how is the value used? Is it the index of a slice? Or
something more abstract?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-01 20:47     ` Channa
@ 2018-02-02 11:08       ` Mark Rutland
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Rutland @ 2018-02-02 11:08 UTC (permalink / raw)
  To: Channa
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan, linux-kernel-owner

On Thu, Feb 01, 2018 at 12:47:01PM -0800, Channa wrote:
> On 2018-02-01 02:48, Mark Rutland wrote:
> > On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
> > > Documentation for last level cache controller device tree bindings,
> > > client bindings usage examples.
> > > 
> > > Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
> > > ---
> > >  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93
> > > ++++++++++++++++++++++
> > >  1 file changed, 93 insertions(+)
> > >  create mode 100644
> > > Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
> > > 
> > > +Example:
> > > +
> > > +	qcom,system-cache@1300000 {
> > > +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
> > > +		reg = <0x1300000 0x50000>;
> > > +		reg-names = "llcc_base";
> > > +
> > > +		llcc: qcom,sdm845-llcc {
> > > +			compatible = "qcom,sdm845-llcc";
> > > +			#cache-cells = <1>;
> > > +			max-slices = <32>;
> > > +		};
> > > +
> > > +		qcom,llcc-ecc {
> > > +			compatible = "qcom,llcc-ecc";
> > > +		};
> > > +
> > > +		qcom,llcc-amon {
> > > +			compatible = "qcom,llcc-amon";
> > > +			qcom,fg-cnt = <0x7>;
> > > +		};
> > > +
> > > +	};
> > 
> > The "qcom,llcc-ecc" and "qcom,llcc-amon" bindings doesn't seem to be
> > used by the driver in patch 2, and it's not clear how they are intended
> > to be used, so I think they should go from the binding for now.
> 
> Sure I can remove them for now and add them when the I push other drivers
> for review.
> 
> > I don't think you need syscon and simple-mfd, and I think you can
> 
> I used syscon and simple-mfd because three drivers touch the same address
> space.

As in my other reply, I don't think that's the right way to solve the
problem.

Please have one top-level driver and associated binding. That driver can
carve up the functional units and allow other drivers to access the
registers as necessary.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-02 11:05       ` Mark Rutland
@ 2018-02-06 19:56         ` Channa
  2018-02-13 14:37           ` Mark Rutland
  0 siblings, 1 reply; 20+ messages in thread
From: Channa @ 2018-02-06 19:56 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On 2018-02-02 03:05, Mark Rutland wrote:
> On Thu, Feb 01, 2018 at 12:39:09PM -0800, Channa wrote:
>> On 2018-02-01 02:44, Mark Rutland wrote:
>> > On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
>> > > Documentation for last level cache controller device tree bindings,
>> > > client bindings usage examples.
>> > >
>> > > Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
>> > > ---
>> > >  .../devicetree/bindings/arm/msm/qcom,llcc.txt      | 93
>> > > ++++++++++++++++++++++
>> > >  1 file changed, 93 insertions(+)
>> > >  create mode 100644
>> > > Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> > >
>> > > diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> > > b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> > > new file mode 100644
>> > > index 0000000..d433b0c
>> > > --- /dev/null
>> > > +++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.txt
>> > > @@ -0,0 +1,93 @@
>> > > +* LLCC (Last Level Cache Controller)
>> > > +
>> > > +Properties:
>> > > +- compatible:
>> > > +	Usage: required
>> > > +	Value type: <string>
>> > > +	Definition: must be "qcom,llcc-core"
>> > > +
>> > > +- reg:
>> > > +	Usage: required
>> > > +	Value Type: <prop-encoded-array>
>> > > +	Definition: must be addresses and sizes of the LLCC registers
>> > > +
>> > > +- llcc-bank-off:
>> > > +	Usage: required
>> > > +	Value Type: <u32 array>
>> > > +	Definition: Offsets of llcc banks from llcc base address starting
>> > > from
>> > > +		    LLCC bank0.
>> > > +
>> > > +- llcc-broadcast-off:
>> > > +	Usage: required
>> > > +	Value Type: <u32>
>> > > +	Definition: Offset of broadcast register from LLCC bank0 address.
>> >
>> > Please could we use "offset" rather than "off" for both of these? That
>> > way it's obvious these aren't properties for disabling some feature.
>> >
>> > How variable are these offsets in practice? Is the memory map not fixed?
>> 
>> The offsets depends on the number of LLCC HW blocks. These number of 
>> HW
>> blocks vary from
>> chipset to chipset and new registers could be added that changes the 
>> offset.
> 
> Surely if new registers are added, we need a new compatible string?
> 
> Can't we encode the number of LLCC HW blocks, instead? Presumably that
> would give enough information to cover both llcc-bank-off and
> llcc-broadcast-off.
> 
> [...]

Are you suggesting to move these offset handing out of DTS files and 
manage in the driver?

> 
>> > > +
>> > > +compatible devices:
>> > > +		qcom,sdm845-llcc
>> >
>> > Huh? The "qcom,sdm845-llcc" bindings wasn't described above, and it's
>> > not clear what this means.
>> >
>> > > +
>> > > +Example:
>> > > +
>> > > +	qcom,system-cache@1300000 {
>> > > +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
>> >
>> > This looks very wrong. Why do you need syscon and simple-mfd?
>> 
>> LLCC HW block has 3 functionalities:
>> System cache core, ECC & AMON drivers for debugging.
>> All three drivers use the same register space for configuration, 
>> status etc.
>> In order to avoid remapping the same address region across multiple 
>> drivers,
>> I have implemented this driver as a syncon and simple-mfd.
> 
> Please don't do that; that's completely dependent on Linux
> implementation details.

Why do you think simple-mfd is not good here? The LLCC HW clock is 
outside of CPUSS and has
multiple functional blocks.

> 
> Have one top level driver for the whole LLCC block, which maps the
> registers, and provides an API for accessing them. When that probes, it
> can cause the other drivers to be probed (e.g. with a platform device),
> and those can access the LLCC registers via that API.
> 
>> > > +		reg = <0x1300000 0x50000>;
>> > > +		reg-names = "llcc_base";
>> > > +
>> > > +		llcc: qcom,sdm845-llcc {
>> > > +			compatible = "qcom,sdm845-llcc";
>> >
>> > Why is this a sub-node?
>> qcom,sdm845-llcc: This core driver as mentioned in the list above.
>> >
>> > Why isn't the top-level node just "qcom,sdm845-llcc" ?
>> >
>> > > +			#cache-cells = <1>;
>> > > +			max-slices = <32>;
>> > > +		};
>> > > +
>> > > +		qcom,llcc-ecc {
>> > > +			compatible = "qcom,llcc-ecc";
>> > > +		};
>> 
>> qcom,llcc-ecc: Driver #2 for ECC
>> 
>> > > +
>> > > +		qcom,llcc-amon {
>> > > +			compatible = "qcom,llcc-amon";
>> > > +			qcom,fg-cnt = <0x7>;
>> > > +		};
>> > > +
>> 
>> qcom,llcc-amon: Driver #3 for AMON
> 
> Please describe the HW, not the drivers.
> 
> As above, I don't believe you need multiple nodes here. Linux can
> instantiate the drivers as necessary.
> 
> [...]
> 
>> > > +- cache-slices:
>> > > +	Usage: required
>> > > +	Value type: <prop-encoded-array>
>> > > +	Definition: The tuple has phandle to llcc device as the first
>> > > argument and the
>> > > +		    second argument is the usecase id of the client.
>> >
>> > What is a "usecase id" ?
>> 
>> Usecase id for use case that wants to use system cache for eg: 
>> video-encode
>> and video-decode
> 
> Sure, but how is the value used? Is it the index of a slice? Or
> something more abstract?

This is used as an index to the SCT (System cache Table) configuration 
data that controls
the behavior of each cache slice.

> 
> Thanks,
> Mark.
-- 
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-01-25 23:55 ` [PATCH 1/2] dt-bindings: Documentation for qcom,llcc Channagoud Kadabi
  2018-02-01 10:44   ` Mark Rutland
  2018-02-01 10:48   ` Mark Rutland
@ 2018-02-08 16:52   ` Matt Sealey
  2018-02-09  0:24     ` Channa
  2 siblings, 1 reply; 20+ messages in thread
From: Matt Sealey @ 2018-02-08 16:52 UTC (permalink / raw)
  To: Channagoud Kadabi
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	Stephen Boyd, kyan

Hiya,

On 25 January 2018 at 17:55, Channagoud Kadabi <ckadabi@codeaurora.org> wrote:
> Documentation for last level cache controller device tree bindings,
> client bindings usage examples.

[snippety snip]

> +- llcc-bank-off:
> +       Usage: required
> +       Value Type: <u32 array>
> +       Definition: Offsets of llcc banks from llcc base address starting from
> +                   LLCC bank0.
> +
> +- llcc-broadcast-off:
> +       Usage: required
> +       Value Type: <u32>
> +       Definition: Offset of broadcast register from LLCC bank0 address.

What's with the redundant namespacing?

Have we not, as a community, realised that we do not need to namespace
properties which are only present under
a single binding or node, or even those that aren't? This mess started
with the regulator bindings and it's never
stopped. What are we at now, 25 years of device trees, 10 years of FDT on Arm?

Notwithstanding the complete waste of rodata in the kernel image for
matching (& increased time to compare), why
wouldn't you consider why "bank-offset" for your node be any different
than a common property for any other node?

And if you need to describe register offsets... why aren't you able to
use the reg property?

Ta,
Matt

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-08 16:52   ` Matt Sealey
@ 2018-02-09  0:24     ` Channa
  2018-02-13 14:33       ` Mark Rutland
  0 siblings, 1 reply; 20+ messages in thread
From: Channa @ 2018-02-09  0:24 UTC (permalink / raw)
  To: Matt Sealey
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	Stephen Boyd, kyan, linux-kernel-owner

On 2018-02-08 08:52, Matt Sealey wrote:
> Hiya,
> 
> On 25 January 2018 at 17:55, Channagoud Kadabi <ckadabi@codeaurora.org> 
> wrote:
>> Documentation for last level cache controller device tree bindings,
>> client bindings usage examples.
> 
> [snippety snip]
> 
>> +- llcc-bank-off:
>> +       Usage: required
>> +       Value Type: <u32 array>
>> +       Definition: Offsets of llcc banks from llcc base address 
>> starting from
>> +                   LLCC bank0.
>> +
>> +- llcc-broadcast-off:
>> +       Usage: required
>> +       Value Type: <u32>
>> +       Definition: Offset of broadcast register from LLCC bank0 
>> address.
> 
> What's with the redundant namespacing?
> 
> Have we not, as a community, realised that we do not need to namespace
> properties which are only present under
> a single binding or node, or even those that aren't? This mess started
> with the regulator bindings and it's never
> stopped. What are we at now, 25 years of device trees, 10 years of FDT 
> on Arm?
> 
> Notwithstanding the complete waste of rodata in the kernel image for
> matching (& increased time to compare), why
> wouldn't you consider why "bank-offset" for your node be any different
> than a common property for any other node?

I will clean up the name space and use bank-offset for the property 
name.

> 
> And if you need to describe register offsets... why aren't you able to
> use the reg property?

Reg property did not suit well for my need, so I choose to maintain 
offsets instead.

The registers in the HW block are organized as
                 (offset1)    (offset2)     (offset3)     (offset4)
Base(Block0) -- Block1 -- Block 2 -- Block 3 -- Broadcast_Block

Each block has identical register mapping. You can think of it as 4 
instances of identical HW.
Broadcast block is to simplify writes, you don't need to write to 
individual blocks instead write to broadcast block.

I use simple-mfd/syscon as the hardware has multiple functions.
Doing regmap on the the Base (Block0) and maintaining offset makes the 
driver cleaner rather than using the reg property for
each instance.

> 
> Ta,
> Matt

-- 
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-09  0:24     ` Channa
@ 2018-02-13 14:33       ` Mark Rutland
  0 siblings, 0 replies; 20+ messages in thread
From: Mark Rutland @ 2018-02-13 14:33 UTC (permalink / raw)
  To: Channa
  Cc: Matt Sealey, linux-arm-kernel, linux-arm-msm, linux-arm,
	linux-kernel, tsoni, Stephen Boyd, kyan, linux-kernel-owner

On Thu, Feb 08, 2018 at 04:24:16PM -0800, Channa wrote:
> On 2018-02-08 08:52, Matt Sealey wrote:
> > On 25 January 2018 at 17:55, Channagoud Kadabi <ckadabi@codeaurora.org>
> > wrote:
> > > Documentation for last level cache controller device tree bindings,
> > > client bindings usage examples.
> > 
> > [snippety snip]
> > 
> > > +- llcc-bank-off:
> > > +       Usage: required
> > > +       Value Type: <u32 array>
> > > +       Definition: Offsets of llcc banks from llcc base address
> > > starting from
> > > +                   LLCC bank0.
> > > +
> > > +- llcc-broadcast-off:
> > > +       Usage: required
> > > +       Value Type: <u32>
> > > +       Definition: Offset of broadcast register from LLCC bank0
> > > address.

> > And if you need to describe register offsets... why aren't you able to
> > use the reg property?
> 
> Reg property did not suit well for my need, so I choose to maintain offsets
> instead.
> 
> The registers in the HW block are organized as
>                 (offset1)    (offset2)     (offset3)     (offset4)
> Base(Block0) -- Block1 -- Block 2 -- Block 3 -- Broadcast_Block
> 
> Each block has identical register mapping. You can think of it as 4
> instances of identical HW.

We have similar in other devices (e.g. GICv3 has multiple instances of
the same register block).

If there's nothing between those blocks, using a reg entry sounds
prefectly reasonable. You can list the broadcast block first, then the
others, or use reg-names.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-06 19:56         ` Channa
@ 2018-02-13 14:37           ` Mark Rutland
  2018-02-13 17:38             ` Channa
  0 siblings, 1 reply; 20+ messages in thread
From: Mark Rutland @ 2018-02-13 14:37 UTC (permalink / raw)
  To: Channa
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On Tue, Feb 06, 2018 at 11:56:50AM -0800, Channa wrote:
> On 2018-02-02 03:05, Mark Rutland wrote:
> > On Thu, Feb 01, 2018 at 12:39:09PM -0800, Channa wrote:
> > > On 2018-02-01 02:44, Mark Rutland wrote:
> > > > On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
> > > > > +- llcc-bank-off:
> > > > > +	Usage: required
> > > > > +	Value Type: <u32 array>
> > > > > +	Definition: Offsets of llcc banks from llcc base address starting
> > > > > from
> > > > > +		    LLCC bank0.
> > > > > +
> > > > > +- llcc-broadcast-off:
> > > > > +	Usage: required
> > > > > +	Value Type: <u32>
> > > > > +	Definition: Offset of broadcast register from LLCC bank0 address.
> > > >
> > > > Please could we use "offset" rather than "off" for both of these? That
> > > > way it's obvious these aren't properties for disabling some feature.
> > > >
> > > > How variable are these offsets in practice? Is the memory map not fixed?
> > > 
> > > The offsets depends on the number of LLCC HW blocks. These number of
> > > HW
> > > blocks vary from
> > > chipset to chipset and new registers could be added that changes the
> > > offset.
> > 
> > Surely if new registers are added, we need a new compatible string?
> > 
> > Can't we encode the number of LLCC HW blocks, instead? Presumably that
> > would give enough information to cover both llcc-bank-off and
> > llcc-broadcast-off.
> > 
> > [...]
> 
> Are you suggesting to move these offset handing out of DTS files and manage
> in the driver?

Something like that, though it depends on how exactly the offsets can be
derived.

Using reg entries, as Matt suggested, sounds better though.

> > > > > +compatible devices:
> > > > > +		qcom,sdm845-llcc
> > > >
> > > > Huh? The "qcom,sdm845-llcc" bindings wasn't described above, and it's
> > > > not clear what this means.
> > > >
> > > > > +
> > > > > +Example:
> > > > > +
> > > > > +	qcom,system-cache@1300000 {
> > > > > +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
> > > >
> > > > This looks very wrong. Why do you need syscon and simple-mfd?
> > > 
> > > LLCC HW block has 3 functionalities:
> > > System cache core, ECC & AMON drivers for debugging.
> > > All three drivers use the same register space for configuration,
> > > status etc.
> > > In order to avoid remapping the same address region across multiple
> > > drivers,
> > > I have implemented this driver as a syncon and simple-mfd.
> > 
> > Please don't do that; that's completely dependent on Linux
> > implementation details.
> 
> Why do you think simple-mfd is not good here? The LLCC HW clock is outside
> of CPUSS and has
> multiple functional blocks.

For one thing, there's no need for this to be a syscon *and* a
simple-mfd.

W.R.T. simple-mfd, I think it would bet better to decompose the device
in a top-level driver, as I described in my prior reply, rather than
describing a set of drivers (which are not themselves HW).

> > > > > +- cache-slices:
> > > > > +	Usage: required
> > > > > +	Value type: <prop-encoded-array>
> > > > > +	Definition: The tuple has phandle to llcc device as the first
> > > > > argument and the
> > > > > +		    second argument is the usecase id of the client.
> > > >
> > > > What is a "usecase id" ?
> > > 
> > > Usecase id for use case that wants to use system cache for eg:
> > > video-encode
> > > and video-decode
> > 
> > Sure, but how is the value used? Is it the index of a slice? Or
> > something more abstract?
> 
> This is used as an index to the SCT (System cache Table) configuration
> data that controls the behavior of each cache slice.

Ok. Where does that SCT live? Is that in HW? Is it programmed by SW, or
statically configured for a given platform?

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 1/2] dt-bindings: Documentation for qcom,llcc
  2018-02-13 14:37           ` Mark Rutland
@ 2018-02-13 17:38             ` Channa
  0 siblings, 0 replies; 20+ messages in thread
From: Channa @ 2018-02-13 17:38 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On 2018-02-13 06:37, Mark Rutland wrote:
> On Tue, Feb 06, 2018 at 11:56:50AM -0800, Channa wrote:
>> On 2018-02-02 03:05, Mark Rutland wrote:
>> > On Thu, Feb 01, 2018 at 12:39:09PM -0800, Channa wrote:
>> > > On 2018-02-01 02:44, Mark Rutland wrote:
>> > > > On Thu, Jan 25, 2018 at 03:55:12PM -0800, Channagoud Kadabi wrote:
>> > > > > +- llcc-bank-off:
>> > > > > +	Usage: required
>> > > > > +	Value Type: <u32 array>
>> > > > > +	Definition: Offsets of llcc banks from llcc base address starting
>> > > > > from
>> > > > > +		    LLCC bank0.
>> > > > > +
>> > > > > +- llcc-broadcast-off:
>> > > > > +	Usage: required
>> > > > > +	Value Type: <u32>
>> > > > > +	Definition: Offset of broadcast register from LLCC bank0 address.
>> > > >
>> > > > Please could we use "offset" rather than "off" for both of these? That
>> > > > way it's obvious these aren't properties for disabling some feature.
>> > > >
>> > > > How variable are these offsets in practice? Is the memory map not fixed?
>> > >
>> > > The offsets depends on the number of LLCC HW blocks. These number of
>> > > HW
>> > > blocks vary from
>> > > chipset to chipset and new registers could be added that changes the
>> > > offset.
>> >
>> > Surely if new registers are added, we need a new compatible string?
>> >
>> > Can't we encode the number of LLCC HW blocks, instead? Presumably that
>> > would give enough information to cover both llcc-bank-off and
>> > llcc-broadcast-off.
>> >
>> > [...]
>> 
>> Are you suggesting to move these offset handing out of DTS files and 
>> manage
>> in the driver?
> 
> Something like that, though it depends on how exactly the offsets can 
> be
> derived.
> 
> Using reg entries, as Matt suggested, sounds better though.
> 
>> > > > > +compatible devices:
>> > > > > +		qcom,sdm845-llcc
>> > > >
>> > > > Huh? The "qcom,sdm845-llcc" bindings wasn't described above, and it's
>> > > > not clear what this means.
>> > > >
>> > > > > +
>> > > > > +Example:
>> > > > > +
>> > > > > +	qcom,system-cache@1300000 {
>> > > > > +		compatible = "qcom,llcc-core", "syscon", "simple-mfd";
>> > > >
>> > > > This looks very wrong. Why do you need syscon and simple-mfd?
>> > >
>> > > LLCC HW block has 3 functionalities:
>> > > System cache core, ECC & AMON drivers for debugging.
>> > > All three drivers use the same register space for configuration,
>> > > status etc.
>> > > In order to avoid remapping the same address region across multiple
>> > > drivers,
>> > > I have implemented this driver as a syncon and simple-mfd.
>> >
>> > Please don't do that; that's completely dependent on Linux
>> > implementation details.
>> 
>> Why do you think simple-mfd is not good here? The LLCC HW clock is 
>> outside
>> of CPUSS and has
>> multiple functional blocks.
> 
> For one thing, there's no need for this to be a syscon *and* a
> simple-mfd.
> 
> W.R.T. simple-mfd, I think it would bet better to decompose the device
> in a top-level driver, as I described in my prior reply, rather than
> describing a set of drivers (which are not themselves HW).
> 
>> > > > > +- cache-slices:
>> > > > > +	Usage: required
>> > > > > +	Value type: <prop-encoded-array>
>> > > > > +	Definition: The tuple has phandle to llcc device as the first
>> > > > > argument and the
>> > > > > +		    second argument is the usecase id of the client.
>> > > >
>> > > > What is a "usecase id" ?
>> > >
>> > > Usecase id for use case that wants to use system cache for eg:
>> > > video-encode
>> > > and video-decode
>> >
>> > Sure, but how is the value used? Is it the index of a slice? Or
>> > something more abstract?
>> 
>> This is used as an index to the SCT (System cache Table) configuration
>> data that controls the behavior of each cache slice.
> 
> Ok. Where does that SCT live? Is that in HW? Is it programmed by SW, or
> statically configured for a given platform?

SCT is in the HW. Kernel driver programs these settings for a given
platform. The table is also used to lookup size, cache slice id details
requested by client drivers.

> 
> Thanks,
> Mark.

-- 
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/2] drivers: soc: Add LLCC driver
  2018-01-25 23:55 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
@ 2018-03-19 14:55   ` Jordan Crouse
  2018-03-23 23:57     ` Channa
  0 siblings, 1 reply; 20+ messages in thread
From: Jordan Crouse @ 2018-03-19 14:55 UTC (permalink / raw)
  To: Channagoud Kadabi
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan

On Thu, Jan 25, 2018 at 03:55:13PM -0800, Channagoud Kadabi wrote:
> LLCC (Last Level Cache Controller) provides additional cache memory
> in the system. LLCC is partitioned into muliple slices and each
> slice gets its own priority, size, ID and other config parameters.
> LLCC driver programs these parameters for each slice. Clients that
> are assigned to use LLCC need to get information such size & ID of the
> slice for their usecase and activate or deactivate the slice as needed.
> LLCC driver provides API interfaces for the clients to perform these
> operations.

<snip>

> +/**
> + * llcc_slice_deactivate - Deactivate the llcc slice
> + * @desc: Pointer to llcc slice descriptor
> + *
> + * A value zero will be returned on success and a negative errno will
> + * be returned in error cases
> + */
> +int llcc_slice_deactivate(struct llcc_slice_desc *desc)
> +{
> +	u32 act_ctrl_val;
> +	int rc = -EINVAL;
> +	struct llcc_drv_data *drv;
> +
> +	if (desc == NULL) {
> +		pr_err("Input descriptor supplied is invalid\n");

Sorry that this is out of the blue, but I was reviewing a client driver that
uses this API. This should not print an error - we should be allowed to safely
pass a null pointer from an aborted sequence in the driver without the
conditional checks and it shouldn't generate a bit of log spam as it goes about
it's business.

Jordan

-- 
The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/2] drivers: soc: Add LLCC driver
  2018-03-19 14:55   ` Jordan Crouse
@ 2018-03-23 23:57     ` Channa
  0 siblings, 0 replies; 20+ messages in thread
From: Channa @ 2018-03-23 23:57 UTC (permalink / raw)
  To: Channagoud Kadabi
  Cc: linux-arm-kernel, linux-arm-msm, linux-arm, linux-kernel, tsoni,
	sboyd, kyan, linux-kernel-owner

On 2018-03-19 07:55, Jordan Crouse wrote:
> On Thu, Jan 25, 2018 at 03:55:13PM -0800, Channagoud Kadabi wrote:
>> LLCC (Last Level Cache Controller) provides additional cache memory
>> in the system. LLCC is partitioned into muliple slices and each
>> slice gets its own priority, size, ID and other config parameters.
>> LLCC driver programs these parameters for each slice. Clients that
>> are assigned to use LLCC need to get information such size & ID of the
>> slice for their usecase and activate or deactivate the slice as 
>> needed.
>> LLCC driver provides API interfaces for the clients to perform these
>> operations.
> 
> <snip>
> 
>> +/**
>> + * llcc_slice_deactivate - Deactivate the llcc slice
>> + * @desc: Pointer to llcc slice descriptor
>> + *
>> + * A value zero will be returned on success and a negative errno will
>> + * be returned in error cases
>> + */
>> +int llcc_slice_deactivate(struct llcc_slice_desc *desc)
>> +{
>> +	u32 act_ctrl_val;
>> +	int rc = -EINVAL;
>> +	struct llcc_drv_data *drv;
>> +
>> +	if (desc == NULL) {
>> +		pr_err("Input descriptor supplied is invalid\n");
> 
> Sorry that this is out of the blue, but I was reviewing a client driver 
> that
> uses this API. This should not print an error - we should be allowed to 
> safely
> pass a null pointer from an aborted sequence in the driver without the
> conditional checks and it shouldn't generate a bit of log spam as it 
> goes about
> it's business.

Thanks Jordan. I will incorporate this change in my next patchset.

> 
> Jordan

-- 
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/2] drivers: soc: Add LLCC driver
  2018-01-16 22:35 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
  2018-01-25 23:39   ` Trilok Soni
@ 2018-01-30  1:57   ` kbuild test robot
  1 sibling, 0 replies; 20+ messages in thread
From: kbuild test robot @ 2018-01-30  1:57 UTC (permalink / raw)
  To: Channagoud Kadabi
  Cc: kbuild-all, linux-arm-msm, linux-arm, linux-kernel, tsoni, sboyd,
	kyan, Channagoud Kadabi

[-- Attachment #1: Type: text/plain, Size: 10565 bytes --]

Hi Channagoud,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on linus/master]
[also build test ERROR on v4.15 next-20180126]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Channagoud-Kadabi/SDM845-System-Cache-Driver/20180119-223446
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

>> drivers/soc/qcom/llcc-slice.c:138:25: error: redefinition of 'llcc_slice_getd'
    struct llcc_slice_desc *llcc_slice_getd(struct device *dev, const char *name)
                            ^~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:111:39: note: previous definition of 'llcc_slice_getd' was here
    static inline struct llcc_slice_desc *llcc_slice_getd(struct device *dev,
                                          ^~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:171:6: error: redefinition of 'llcc_slice_putd'
    void llcc_slice_putd(struct llcc_slice_desc *desc)
         ^~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:117:20: note: previous definition of 'llcc_slice_putd' was here
    static inline void llcc_slice_putd(struct llcc_slice_desc *desc)
                       ^~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:214:5: error: redefinition of 'llcc_slice_activate'
    int llcc_slice_activate(struct llcc_slice_desc *desc)
        ^~~~~~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:131:19: note: previous definition of 'llcc_slice_activate' was here
    static inline int llcc_slice_activate(struct llcc_slice_desc *desc)
                      ^~~~~~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:257:5: error: redefinition of 'llcc_slice_deactivate'
    int llcc_slice_deactivate(struct llcc_slice_desc *desc)
        ^~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:136:19: note: previous definition of 'llcc_slice_deactivate' was here
    static inline int llcc_slice_deactivate(struct llcc_slice_desc *desc)
                      ^~~~~~~~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:299:5: error: redefinition of 'llcc_get_slice_id'
    int llcc_get_slice_id(struct llcc_slice_desc *desc)
        ^~~~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:122:19: note: previous definition of 'llcc_get_slice_id' was here
    static inline int llcc_get_slice_id(struct llcc_slice_desc *desc)
                      ^~~~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:315:8: error: redefinition of 'llcc_get_slice_size'
    size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
           ^~~~~~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:127:22: note: previous definition of 'llcc_get_slice_size' was here
    static inline size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
                         ^~~~~~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:384:5: error: redefinition of 'qcom_llcc_probe'
    int qcom_llcc_probe(struct platform_device *pdev,
        ^~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:140:19: note: previous definition of 'qcom_llcc_probe' was here
    static inline int qcom_llcc_probe(struct platform_device *pdev,
                      ^~~~~~~~~~~~~~~
>> drivers/soc/qcom/llcc-slice.c:443:5: error: redefinition of 'qcom_llcc_remove'
    int qcom_llcc_remove(struct platform_device *pdev)
        ^~~~~~~~~~~~~~~~
   In file included from drivers/soc/qcom/llcc-slice.c:28:0:
   include/linux/soc/qcom/llcc-qcom.h:146:19: note: previous definition of 'qcom_llcc_remove' was here
    static inline int qcom_llcc_remove(struct platform_device *pdev)
                      ^~~~~~~~~~~~~~~~

vim +/llcc_slice_getd +138 drivers/soc/qcom/llcc-slice.c

   129	
   130	/**
   131	 * llcc_slice_getd - get llcc slice descriptor
   132	 * @dev: Device pointer of the client
   133	 * @name: Name of the use case
   134	 *
   135	 * A pointer to llcc slice descriptor will be returned on success and
   136	 * and error pointer is returned on failure
   137	 */
 > 138	struct llcc_slice_desc *llcc_slice_getd(struct device *dev, const char *name)
   139	{
   140		struct device_node *np = dev->of_node;
   141		int index = 0;
   142		const char *slice_name;
   143		struct property *prop;
   144	
   145		if (!np) {
   146			dev_err(dev, "%s() currently only supports DT\n", __func__);
   147			return ERR_PTR(-ENOENT);
   148		}
   149	
   150		if (!of_get_property(np, "cache-slice-names", NULL)) {
   151			dev_err(dev,
   152				"%s() requires a \"cache-slice-names\" property\n",
   153				__func__);
   154			return ERR_PTR(-ENOENT);
   155		}
   156	
   157		of_property_for_each_string(np, "cache-slice-names", prop, slice_name) {
   158			if (!strcmp(name, slice_name))
   159				break;
   160			index++;
   161		}
   162	
   163		return llcc_slice_get_entry(dev, index);
   164	}
   165	EXPORT_SYMBOL(llcc_slice_getd);
   166	
   167	/**
   168	 * llcc_slice_putd - llcc slice descritpor
   169	 * @desc: Pointer to llcc slice descriptor
   170	 */
 > 171	void llcc_slice_putd(struct llcc_slice_desc *desc)
   172	{
   173		kfree(desc);
   174	}
   175	EXPORT_SYMBOL(llcc_slice_putd);
   176	
   177	static int llcc_update_act_ctrl(struct llcc_drv_data *drv, u32 sid,
   178					u32 act_ctrl_reg_val, u32 status)
   179	{
   180		u32 act_ctrl_reg;
   181		u32 status_reg;
   182		u32 slice_status;
   183		unsigned long timeout;
   184	
   185		act_ctrl_reg = drv->b_off + LLCC_TRP_ACT_CTRLn(sid);
   186		status_reg = drv->b_off + LLCC_TRP_STATUSn(sid);
   187	
   188		regmap_write(drv->llcc_map, act_ctrl_reg, act_ctrl_reg_val);
   189	
   190		/* Make sure the activate trigger is applied before clearing it */
   191		mb();
   192	
   193		/* Clear the ACTIVE trigger */
   194		act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
   195		regmap_write(drv->llcc_map, act_ctrl_reg, act_ctrl_reg_val);
   196	
   197		timeout = jiffies + usecs_to_jiffies(LLCC_STATUS_READ_DELAY);
   198		while (time_before(jiffies, timeout)) {
   199			regmap_read(drv->llcc_map, status_reg, &slice_status);
   200			if (!(slice_status & status))
   201				return 0;
   202		}
   203	
   204		return -ETIMEDOUT;
   205	}
   206	
   207	/**
   208	 * llcc_slice_activate - Activate the llcc slice
   209	 * @desc: Pointer to llcc slice descriptor
   210	 *
   211	 * A value zero will be returned on success and a negative errno will
   212	 * be returned in error cases
   213	 */
 > 214	int llcc_slice_activate(struct llcc_slice_desc *desc)
   215	{
   216		int rc = -EINVAL;
   217		u32 act_ctrl_val;
   218		struct llcc_drv_data *drv;
   219	
   220		if (desc == NULL) {
   221			pr_err("Input descriptor supplied is invalid\n");
   222			return rc;
   223		}
   224	
   225		drv = dev_get_drvdata(desc->dev);
   226		if (!drv) {
   227			pr_err("Invalid device pointer in the desc\n");
   228			return rc;
   229		}
   230	
   231		mutex_lock(&drv->slice_mutex);
   232		if (test_bit(desc->llcc_slice_id, drv->llcc_slice_map)) {
   233			mutex_unlock(&drv->slice_mutex);
   234			return 0;
   235		}
   236	
   237		act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT;
   238		act_ctrl_val |= ACT_CTRL_ACT_TRIG;
   239	
   240		rc = llcc_update_act_ctrl(drv, desc->llcc_slice_id, act_ctrl_val,
   241					  DEACTIVATE);
   242	
   243		__set_bit(desc->llcc_slice_id, drv->llcc_slice_map);
   244		mutex_unlock(&drv->slice_mutex);
   245	
   246		return rc;
   247	}
   248	EXPORT_SYMBOL(llcc_slice_activate);
   249	
   250	/**
   251	 * llcc_slice_deactivate - Deactivate the llcc slice
   252	 * @desc: Pointer to llcc slice descriptor
   253	 *
   254	 * A value zero will be returned on success and a negative errno will
   255	 * be returned in error cases
   256	 */
 > 257	int llcc_slice_deactivate(struct llcc_slice_desc *desc)
   258	{
   259		u32 act_ctrl_val;
   260		int rc = -EINVAL;
   261		struct llcc_drv_data *drv;
   262	
   263		if (desc == NULL) {
   264			pr_err("Input descriptor supplied is invalid\n");
   265			return rc;
   266		}
   267	
   268		drv = dev_get_drvdata(desc->dev);
   269		if (!drv) {
   270			pr_err("Invalid device pointer in the desc\n");
   271			return rc;
   272		}
   273	
   274		mutex_lock(&drv->slice_mutex);
   275		if (!test_bit(desc->llcc_slice_id, drv->llcc_slice_map)) {
   276			mutex_unlock(&drv->slice_mutex);
   277			return 0;
   278		}
   279		act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
   280		act_ctrl_val |= ACT_CTRL_ACT_TRIG;
   281	
   282		rc = llcc_update_act_ctrl(drv, desc->llcc_slice_id, act_ctrl_val,
   283					  ACTIVATE);
   284	
   285		__clear_bit(desc->llcc_slice_id, drv->llcc_slice_map);
   286		mutex_unlock(&drv->slice_mutex);
   287	
   288		return rc;
   289	}
   290	EXPORT_SYMBOL(llcc_slice_deactivate);
   291	
   292	/**
   293	 * llcc_get_slice_id - return the slice id
   294	 * @desc: Pointer to llcc slice descriptor
   295	 *
   296	 * A positive value will be returned on success and a negative errno will
   297	 * be returned on error
   298	 */
 > 299	int llcc_get_slice_id(struct llcc_slice_desc *desc)
   300	{
   301		if (!desc)
   302			return -EINVAL;
   303	
   304		return desc->llcc_slice_id;
   305	}
   306	EXPORT_SYMBOL(llcc_get_slice_id);
   307	
   308	/**
   309	 * llcc_get_slice_size - return the slice id
   310	 * @desc: Pointer to llcc slice descriptor
   311	 *
   312	 * A positive value will be returned on success and zero will returned on
   313	 * error
   314	 */
 > 315	size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
   316	{
   317		if (!desc)
   318			return 0;
   319	
   320		return desc->llcc_slice_size;
   321	}
   322	EXPORT_SYMBOL(llcc_get_slice_size);
   323	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 58559 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 2/2] drivers: soc: Add LLCC driver
  2018-01-16 22:35 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
@ 2018-01-25 23:39   ` Trilok Soni
  2018-01-30  1:57   ` kbuild test robot
  1 sibling, 0 replies; 20+ messages in thread
From: Trilok Soni @ 2018-01-25 23:39 UTC (permalink / raw)
  To: Channagoud Kadabi, linux-arm-msm; +Cc: linux-arm, linux-kernel, sboyd, kyan


On 1/16/2018 2:35 PM, Channagoud Kadabi wrote:
> LLCC (Last Level Cache Controller) provides additional cache memory
> in the system. LLCC is partitioned into muliple slices and each
> slice gets its own priority, size, ID and other config parameters.
> LLCC driver programs these parameters for each slice. Clients that
> are assigned to use LLCC need to get information such size & ID of the
> slice for their usecase and activate or deactivate the slice as needed.
> LLCC driver provides API interfaces for the clients to perform these
> operations.

Steve/linux-arm-msm folks, please provide review comments to system 
cache driver patch series.

---Trilok Soni--

The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 2/2] drivers: soc: Add LLCC driver
  2018-01-16 22:35 [PATCH 0/2] SDM845 System Cache Driver Channagoud Kadabi
@ 2018-01-16 22:35 ` Channagoud Kadabi
  2018-01-25 23:39   ` Trilok Soni
  2018-01-30  1:57   ` kbuild test robot
  0 siblings, 2 replies; 20+ messages in thread
From: Channagoud Kadabi @ 2018-01-16 22:35 UTC (permalink / raw)
  To: linux-arm-msm
  Cc: linux-arm, linux-kernel, tsoni, sboyd, kyan, Channagoud Kadabi

LLCC (Last Level Cache Controller) provides additional cache memory
in the system. LLCC is partitioned into muliple slices and each
slice gets its own priority, size, ID and other config parameters.
LLCC driver programs these parameters for each slice. Clients that
are assigned to use LLCC need to get information such size & ID of the
slice for their usecase and activate or deactivate the slice as needed.
LLCC driver provides API interfaces for the clients to perform these
operations.

Signed-off-by: Channagoud Kadabi <ckadabi@codeaurora.org>
---
 drivers/soc/qcom/Kconfig           |  16 ++
 drivers/soc/qcom/Makefile          |   2 +
 drivers/soc/qcom/llcc-core.c       | 120 ++++++++++
 drivers/soc/qcom/llcc-sdm845.c     | 102 +++++++++
 drivers/soc/qcom/llcc-slice.c      | 456 +++++++++++++++++++++++++++++++++++++
 include/linux/soc/qcom/llcc-qcom.h | 152 +++++++++++++
 6 files changed, 848 insertions(+)
 create mode 100644 drivers/soc/qcom/llcc-core.c
 create mode 100644 drivers/soc/qcom/llcc-sdm845.c
 create mode 100644 drivers/soc/qcom/llcc-slice.c
 create mode 100644 include/linux/soc/qcom/llcc-qcom.h

diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index b81374b..c9bfe44 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -89,6 +89,22 @@ config QCOM_SMSM
 	  Say yes here to support the Qualcomm Shared Memory State Machine.
 	  The state machine is represented by bits in shared memory.
 
+config QCOM_LLCC
+	tristate "Qualcomm Technologies, Inc. LLCC driver"
+	depends on ARCH_QCOM
+	help
+	  Qualcomm Technologies, Inc. platform specific LLCC driver for Last
+	  Level Cache. This provides interfaces to client's that use the LLCC.
+	  Say yes here to enable LLCC slice driver.
+
+config QCOM_SDM845_LLCC
+	tristate "Qualcomm Technologies, Inc. SDM845 LLCC driver"
+	depends on QCOM_LLCC
+	help
+	  Say yes here to enable the LLCC driver for SDM845. This is provides
+	  data required to configure LLCC so that clients can start using the
+	  LLCC slices.
+
 config QCOM_WCNSS_CTRL
 	tristate "Qualcomm WCNSS control driver"
 	depends on ARCH_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index 40c56f6..2dc917e 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_QCOM_GLINK_SSR) +=	glink_ssr.o
+obj-$(CONFIG_QCOM_LLCC) += llcc-core.o llcc-slice.o
+obj-$(CONFIG_QCOM_SDM845_LLCC) += llcc-sdm845.o
 obj-$(CONFIG_QCOM_GSBI)	+=	qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)	+= mdt_loader.o
 obj-$(CONFIG_QCOM_PM)	+=	spm.o
diff --git a/drivers/soc/qcom/llcc-core.c b/drivers/soc/qcom/llcc-core.c
new file mode 100644
index 0000000..53289bb
--- /dev/null
+++ b/drivers/soc/qcom/llcc-core.c
@@ -0,0 +1,120 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+/* Config registers offsets*/
+#define DRP_ECC_ERROR_CFG	0x00040000
+
+/* TRP, DRP interrupt register offsets */
+#define CMN_INTERRUPT_0_ENABLE		0x0003001C
+#define CMN_INTERRUPT_2_ENABLE		0x0003003C
+#define TRP_INTERRUPT_0_ENABLE		0x00020488
+#define DRP_INTERRUPT_ENABLE		0x0004100C
+
+#define SB_ERROR_THRESHOLD	0x1
+#define SB_ERROR_THRESHOLD_SHIFT	24
+#define SB_DB_TRP_INTERRUPT_ENABLE	0x3
+#define TRP0_INTERRUPT_ENABLE	0x1
+#define DRP0_INTERRUPT_ENABLE	BIT(6)
+#define SB_DB_DRP_INTERRUPT_ENABLE	0x3
+
+#ifdef CONFIG_EDAC_QCOM_LLCC
+#define ENABLE_ECC_INTR 1
+#else
+#define ENABLE_ECC_INTR 0
+#endif
+
+static int enable_ecc_intr = ENABLE_ECC_INTR;
+module_param(enable_ecc_intr, int, 0444);
+
+static void qcom_llcc_core_setup(struct regmap *llcc_regmap, uint32_t b_off)
+{
+	u32 sb_err_threshold;
+
+	/* Enable TRP in instance 2 of common interrupt enable register */
+	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
+			   TRP0_INTERRUPT_ENABLE, TRP0_INTERRUPT_ENABLE);
+
+	/* Enable ECC interrupts on Tag Ram */
+	regmap_update_bits(llcc_regmap, b_off + TRP_INTERRUPT_0_ENABLE,
+		SB_DB_TRP_INTERRUPT_ENABLE, SB_DB_TRP_INTERRUPT_ENABLE);
+
+	/* Enable SB error for Data RAM */
+	sb_err_threshold = (SB_ERROR_THRESHOLD << SB_ERROR_THRESHOLD_SHIFT);
+	regmap_write(llcc_regmap, b_off + DRP_ECC_ERROR_CFG, sb_err_threshold);
+
+	/* Enable DRP in instance 2 of common interrupt enable register */
+	regmap_update_bits(llcc_regmap, b_off + CMN_INTERRUPT_2_ENABLE,
+			   DRP0_INTERRUPT_ENABLE, DRP0_INTERRUPT_ENABLE);
+
+	/* Enable ECC interrupts on Data Ram */
+	regmap_write(llcc_regmap, b_off + DRP_INTERRUPT_ENABLE,
+		     SB_DB_DRP_INTERRUPT_ENABLE);
+}
+
+static int qcom_llcc_core_probe(struct platform_device *pdev)
+{
+	struct regmap *llcc_regmap;
+	struct device *dev = &pdev->dev;
+	u32 b_off = 0;
+	int ret = 0;
+
+	llcc_regmap = syscon_node_to_regmap(dev->of_node);
+
+	if (IS_ERR(llcc_regmap)) {
+		dev_err(&pdev->dev, "Cannot find regmap for llcc\n");
+		return PTR_ERR(llcc_regmap);
+	}
+
+	ret = of_property_read_u32(dev->of_node,
+			"qcom,llcc-broadcast-off", &b_off);
+	if (ret) {
+		dev_err(&pdev->dev, "Unable to read broadcast-off\n");
+		return -EINVAL;
+	}
+
+	if (enable_ecc_intr)
+		qcom_llcc_core_setup(llcc_regmap, b_off);
+
+	return 0;
+}
+
+static int qcom_llcc_core_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id qcom_llcc_core_match_table[] = {
+	{ .compatible = "qcom,llcc-core" },
+	{ },
+};
+
+static struct platform_driver qcom_llcc_core_driver = {
+	.probe = qcom_llcc_core_probe,
+	.remove = qcom_llcc_core_remove,
+	.driver = {
+		.name = "qcom_llcc_core",
+		.of_match_table = qcom_llcc_core_match_table,
+	},
+};
+module_platform_driver(qcom_llcc_core_driver);
+
+MODULE_DESCRIPTION("QCOM LLCC Core Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
new file mode 100644
index 0000000..74a63f77
--- /dev/null
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -0,0 +1,102 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+/*
+ * SCT entry contains of the following parameters
+ * name: Name of the client's use case for which the llcc slice is used
+ * uid: Unique id for the client's use case
+ * slice_id: llcc slice id for each client
+ * max_cap: The maximum capacity of the cache slice provided in KB
+ * priority: Priority of the client used to select victim line for replacement
+ * fixed_size: Determine of the slice has a fixed capacity
+ * bonus_ways: Bonus ways to be used by any slice, bonus way is used only if
+ *             it't not a reserved way.
+ * res_ways: Reserved ways for the cache slice, the reserved ways cannot be used
+ *           by any other client than the one its assigned to.
+ * cache_mode: Each slice operates as a cache, this controls the mode of the
+ *             slice normal or TCM
+ * probe_target_ways: Determines what ways to probe for access hit. When
+ *                    configured to 1 only bonus and reseved ways are probed.
+ *                    when configured to 0 all ways in llcc are probed.
+ * dis_cap_alloc: Disable capacity based allocation for a client
+ * retain_on_pc: If this bit is set and client has maitained active vote
+ *               then the ways assigned to this client are not flushed on power
+ *               collapse.
+ * activate_on_init: Activate the slice immidiately after the SCT is programmed
+ */
+#define SCT_ENTRY(n, uid, sid, mc, p, fs, bway, rway, cmod, ptw, dca, rp, a) \
+	{					\
+		.name = n,			\
+		.usecase_id = uid,		\
+		.slice_id = sid,		\
+		.max_cap = mc,			\
+		.priority = p,			\
+		.fixed_size = fs,		\
+		.bonus_ways = bway,		\
+		.res_ways = rway,		\
+		.cache_mode = cmod,		\
+		.probe_target_ways = ptw,	\
+		.dis_cap_alloc = dca,		\
+		.retain_on_pc = rp,		\
+		.activate_on_init = a,		\
+	}
+
+static struct llcc_slice_config sdm845_data[] =  {
+	SCT_ENTRY("cpuss",       1, 1, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 1),
+	SCT_ENTRY("vidsc0",      2, 2, 512, 2, 1, 0x0,  0x0F0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("vidsc1",      3, 3, 512, 2, 1, 0x0,  0x0F0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("rotator",     4, 4, 563, 2, 1, 0x0,  0x00e, 2, 0, 1, 1, 0),
+	SCT_ENTRY("voice",       5, 5, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("audio",       6, 6, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0x0FC, 0xF00, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modem",       8, 8, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("compute",     10, 10, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("gpuhtw",      11, 11, 512, 1, 1, 0xC,  0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("gpu",         12, 12, 2304, 1, 0, 0xFF0, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("mmuhwt",      13, 13, 256, 2, 0, 0x0,  0x1, 0, 0, 1, 0, 1),
+	SCT_ENTRY("compute_dma", 15, 15, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("display",     16, 16, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("videofw",     17, 17, 2816, 1, 0, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0x0,  0xF00, 0, 0, 1, 1, 0),
+	SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0x1e, 0x0, 0, 0, 1, 1, 0),
+	SCT_ENTRY("audiohw",     22, 22, 1024, 1, 1, 0xFFC, 0x2, 0, 0, 1, 1, 0),
+};
+
+static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
+{
+	return qcom_llcc_probe(pdev, sdm845_data,
+				 ARRAY_SIZE(sdm845_data));
+}
+
+static const struct of_device_id sdm845_qcom_llcc_of_match[] = {
+	{ .compatible = "qcom,sdm845-llcc", },
+	{ },
+};
+
+static struct platform_driver sdm845_qcom_llcc_driver = {
+	.driver = {
+		.name = "sdm845-llcc",
+		.of_match_table = sdm845_qcom_llcc_of_match,
+	},
+	.probe = sdm845_qcom_llcc_probe,
+	.remove = qcom_llcc_remove,
+};
+module_platform_driver(sdm845_qcom_llcc_driver);
+
+MODULE_DESCRIPTION("QTI sdm845 LLCC driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c
new file mode 100644
index 0000000..e67a1ef
--- /dev/null
+++ b/drivers/soc/qcom/llcc-slice.c
@@ -0,0 +1,456 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt)  "%s:" fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/bitmap.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
+#define ACTIVATE                      0x1
+#define DEACTIVATE                    0x2
+#define ACT_CTRL_OPCODE_ACTIVATE      0x1
+#define ACT_CTRL_OPCODE_DEACTIVATE    0x2
+#define ACT_CTRL_ACT_TRIG             0x1
+#define ACT_CTRL_OPCODE_SHIFT         0x1
+#define ATTR1_PROBE_TARGET_WAYS_SHIFT 0x2
+#define ATTR1_FIXED_SIZE_SHIFT        0x3
+#define ATTR1_PRIORITY_SHIFT          0x4
+#define ATTR1_MAX_CAP_SHIFT           0x10
+#define ATTR0_RES_WAYS_MASK           0x00000fff
+#define ATR0_BONUS_WAYS_MASK          0x0fff0000
+#define ATR0_BONUS_WAYS_SHIFT         0x10
+#define LLCC_STATUS_READ_DELAY 100
+
+#define CACHE_LINE_SIZE_SHIFT 6
+
+#define LLCC_COMMON_STATUS0		0x0003000C
+#define LLCC_LB_CNT_MASK		0xf0000000
+#define LLCC_LB_CNT_SHIFT		28
+
+#define MAX_CAP_TO_BYTES(n) (n * 1024)
+#define LLCC_TRP_ACT_CTRLn(n) (n * 0x1000)
+#define LLCC_TRP_STATUSn(n)   (4 + n * 0x1000)
+#define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + 0x8 * n)
+#define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + 0x8 * n)
+
+/**
+ * Driver data for llcc
+ * @llcc_virt_base: base address for llcc controller
+ * @slice_data: pointer to llcc slice config data
+ * @sz: Size of the config data table
+ * @llcc_slice_map: Bit map to track the active slice ids
+ */
+struct llcc_drv_data {
+	struct regmap *llcc_map;
+	const struct llcc_slice_config *slice_data;
+	struct mutex slice_mutex;
+	u32 llcc_config_data_sz;
+	u32 max_slices;
+	u32 b_off;
+	u32 no_banks;
+	unsigned long *llcc_slice_map;
+};
+
+/* Get the slice entry by index */
+static struct llcc_slice_desc *llcc_slice_get_entry(struct device *dev, int n)
+{
+	struct of_phandle_args phargs;
+	struct llcc_drv_data *drv;
+	const struct llcc_slice_config *llcc_data_ptr;
+	struct llcc_slice_desc *desc;
+	struct platform_device *pdev;
+	u32 sz, count;
+
+	if (of_parse_phandle_with_args(dev->of_node, "cache-slices",
+				       "#cache-cells", n, &phargs)) {
+		pr_err("can't parse \"cache-slices\" property\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	pdev = of_find_device_by_node(phargs.np);
+	if (!pdev) {
+		pr_err("Cannot find platform device from phandle\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	drv = platform_get_drvdata(pdev);
+	if (!drv) {
+		pr_err("cannot find platform driver data\n");
+		return ERR_PTR(-EFAULT);
+	}
+
+	llcc_data_ptr = drv->slice_data;
+	sz = drv->llcc_config_data_sz;
+	count = 0;
+
+	while (llcc_data_ptr && count < sz) {
+		if (llcc_data_ptr->usecase_id == phargs.args[0])
+			break;
+		llcc_data_ptr++;
+		count++;
+	}
+
+	if (llcc_data_ptr == NULL || count == sz) {
+		pr_err("can't find %d usecase id\n", phargs.args[0]);
+		return ERR_PTR(-ENODEV);
+	}
+
+	desc = kzalloc(sizeof(struct llcc_slice_desc), GFP_KERNEL);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->llcc_slice_id = llcc_data_ptr->slice_id;
+	desc->llcc_slice_size = llcc_data_ptr->max_cap;
+	desc->dev = &pdev->dev;
+
+	return desc;
+}
+
+/**
+ * llcc_slice_getd - get llcc slice descriptor
+ * @dev: Device pointer of the client
+ * @name: Name of the use case
+ *
+ * A pointer to llcc slice descriptor will be returned on success and
+ * and error pointer is returned on failure
+ */
+struct llcc_slice_desc *llcc_slice_getd(struct device *dev, const char *name)
+{
+	struct device_node *np = dev->of_node;
+	int index = 0;
+	const char *slice_name;
+	struct property *prop;
+
+	if (!np) {
+		dev_err(dev, "%s() currently only supports DT\n", __func__);
+		return ERR_PTR(-ENOENT);
+	}
+
+	if (!of_get_property(np, "cache-slice-names", NULL)) {
+		dev_err(dev,
+			"%s() requires a \"cache-slice-names\" property\n",
+			__func__);
+		return ERR_PTR(-ENOENT);
+	}
+
+	of_property_for_each_string(np, "cache-slice-names", prop, slice_name) {
+		if (!strcmp(name, slice_name))
+			break;
+		index++;
+	}
+
+	return llcc_slice_get_entry(dev, index);
+}
+EXPORT_SYMBOL(llcc_slice_getd);
+
+/**
+ * llcc_slice_putd - llcc slice descritpor
+ * @desc: Pointer to llcc slice descriptor
+ */
+void llcc_slice_putd(struct llcc_slice_desc *desc)
+{
+	kfree(desc);
+}
+EXPORT_SYMBOL(llcc_slice_putd);
+
+static int llcc_update_act_ctrl(struct llcc_drv_data *drv, u32 sid,
+				u32 act_ctrl_reg_val, u32 status)
+{
+	u32 act_ctrl_reg;
+	u32 status_reg;
+	u32 slice_status;
+	unsigned long timeout;
+
+	act_ctrl_reg = drv->b_off + LLCC_TRP_ACT_CTRLn(sid);
+	status_reg = drv->b_off + LLCC_TRP_STATUSn(sid);
+
+	regmap_write(drv->llcc_map, act_ctrl_reg, act_ctrl_reg_val);
+
+	/* Make sure the activate trigger is applied before clearing it */
+	mb();
+
+	/* Clear the ACTIVE trigger */
+	act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG;
+	regmap_write(drv->llcc_map, act_ctrl_reg, act_ctrl_reg_val);
+
+	timeout = jiffies + usecs_to_jiffies(LLCC_STATUS_READ_DELAY);
+	while (time_before(jiffies, timeout)) {
+		regmap_read(drv->llcc_map, status_reg, &slice_status);
+		if (!(slice_status & status))
+			return 0;
+	}
+
+	return -ETIMEDOUT;
+}
+
+/**
+ * llcc_slice_activate - Activate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A value zero will be returned on success and a negative errno will
+ * be returned in error cases
+ */
+int llcc_slice_activate(struct llcc_slice_desc *desc)
+{
+	int rc = -EINVAL;
+	u32 act_ctrl_val;
+	struct llcc_drv_data *drv;
+
+	if (desc == NULL) {
+		pr_err("Input descriptor supplied is invalid\n");
+		return rc;
+	}
+
+	drv = dev_get_drvdata(desc->dev);
+	if (!drv) {
+		pr_err("Invalid device pointer in the desc\n");
+		return rc;
+	}
+
+	mutex_lock(&drv->slice_mutex);
+	if (test_bit(desc->llcc_slice_id, drv->llcc_slice_map)) {
+		mutex_unlock(&drv->slice_mutex);
+		return 0;
+	}
+
+	act_ctrl_val = ACT_CTRL_OPCODE_ACTIVATE << ACT_CTRL_OPCODE_SHIFT;
+	act_ctrl_val |= ACT_CTRL_ACT_TRIG;
+
+	rc = llcc_update_act_ctrl(drv, desc->llcc_slice_id, act_ctrl_val,
+				  DEACTIVATE);
+
+	__set_bit(desc->llcc_slice_id, drv->llcc_slice_map);
+	mutex_unlock(&drv->slice_mutex);
+
+	return rc;
+}
+EXPORT_SYMBOL(llcc_slice_activate);
+
+/**
+ * llcc_slice_deactivate - Deactivate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A value zero will be returned on success and a negative errno will
+ * be returned in error cases
+ */
+int llcc_slice_deactivate(struct llcc_slice_desc *desc)
+{
+	u32 act_ctrl_val;
+	int rc = -EINVAL;
+	struct llcc_drv_data *drv;
+
+	if (desc == NULL) {
+		pr_err("Input descriptor supplied is invalid\n");
+		return rc;
+	}
+
+	drv = dev_get_drvdata(desc->dev);
+	if (!drv) {
+		pr_err("Invalid device pointer in the desc\n");
+		return rc;
+	}
+
+	mutex_lock(&drv->slice_mutex);
+	if (!test_bit(desc->llcc_slice_id, drv->llcc_slice_map)) {
+		mutex_unlock(&drv->slice_mutex);
+		return 0;
+	}
+	act_ctrl_val = ACT_CTRL_OPCODE_DEACTIVATE << ACT_CTRL_OPCODE_SHIFT;
+	act_ctrl_val |= ACT_CTRL_ACT_TRIG;
+
+	rc = llcc_update_act_ctrl(drv, desc->llcc_slice_id, act_ctrl_val,
+				  ACTIVATE);
+
+	__clear_bit(desc->llcc_slice_id, drv->llcc_slice_map);
+	mutex_unlock(&drv->slice_mutex);
+
+	return rc;
+}
+EXPORT_SYMBOL(llcc_slice_deactivate);
+
+/**
+ * llcc_get_slice_id - return the slice id
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A positive value will be returned on success and a negative errno will
+ * be returned on error
+ */
+int llcc_get_slice_id(struct llcc_slice_desc *desc)
+{
+	if (!desc)
+		return -EINVAL;
+
+	return desc->llcc_slice_id;
+}
+EXPORT_SYMBOL(llcc_get_slice_id);
+
+/**
+ * llcc_get_slice_size - return the slice id
+ * @desc: Pointer to llcc slice descriptor
+ *
+ * A positive value will be returned on success and zero will returned on
+ * error
+ */
+size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
+{
+	if (!desc)
+		return 0;
+
+	return desc->llcc_slice_size;
+}
+EXPORT_SYMBOL(llcc_get_slice_size);
+
+static void qcom_llcc_cfg_program(struct platform_device *pdev)
+{
+	int i;
+	u32 attr1_cfg;
+	u32 attr0_cfg;
+	u32 attr1_val;
+	u32 attr0_val;
+	u32 max_cap_cacheline;
+	u32 sz;
+	const struct llcc_slice_config *llcc_table;
+	struct llcc_drv_data *drv = platform_get_drvdata(pdev);
+	struct llcc_slice_desc desc;
+	u32 b_off = drv->b_off;
+
+	sz = drv->llcc_config_data_sz;
+	llcc_table = drv->slice_data;
+
+	for (i = 0; i < sz; i++) {
+		attr1_cfg = b_off + LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id);
+		attr0_cfg = b_off + LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id);
+
+		attr1_val = llcc_table[i].cache_mode;
+		attr1_val |= (llcc_table[i].probe_target_ways <<
+				ATTR1_PROBE_TARGET_WAYS_SHIFT);
+		attr1_val |= (llcc_table[i].fixed_size <<
+				ATTR1_FIXED_SIZE_SHIFT);
+		attr1_val |= (llcc_table[i].priority << ATTR1_PRIORITY_SHIFT);
+
+		max_cap_cacheline = MAX_CAP_TO_BYTES(llcc_table[i].max_cap);
+
+		/* LLCC instances can vary for each target.
+		 * The SW writes to broadcast register which gets propagated
+		 * to each llcc instace (llcc0,.. llccN).
+		 * Since the size of the memory is divided equally amongst the
+		 * llcc instances, we need to configure the max cap accordingly.
+		 */
+		max_cap_cacheline = (max_cap_cacheline / drv->no_banks);
+		max_cap_cacheline >>= CACHE_LINE_SIZE_SHIFT;
+		attr1_val |= (max_cap_cacheline << ATTR1_MAX_CAP_SHIFT);
+
+		attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK;
+		attr0_val |= llcc_table[i].bonus_ways << ATR0_BONUS_WAYS_SHIFT;
+
+		regmap_write(drv->llcc_map, attr1_cfg, attr1_val);
+		regmap_write(drv->llcc_map, attr0_cfg, attr0_val);
+
+		/* Make sure that the SCT is programmed before activating */
+		mb();
+
+		if (llcc_table[i].activate_on_init) {
+			desc.llcc_slice_id = llcc_table[i].slice_id;
+			desc.dev = &pdev->dev;
+			if (llcc_slice_activate(&desc)) {
+				pr_err("activate slice id: %d timed out\n",
+						desc.llcc_slice_id);
+			}
+		}
+	}
+}
+
+int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *llcc_cfg, u32 sz)
+{
+	int rc = 0;
+	u32 num_banks = 0;
+	struct device *dev = &pdev->dev;
+	static struct llcc_drv_data *drv_data;
+
+	drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return PTR_ERR(drv_data);
+
+	drv_data->llcc_map = syscon_node_to_regmap(dev->parent->of_node);
+	if (!drv_data->llcc_map)
+		return PTR_ERR(drv_data->llcc_map);
+
+	regmap_read(drv_data->llcc_map, LLCC_COMMON_STATUS0,
+		    &num_banks);
+
+	num_banks &= LLCC_LB_CNT_MASK;
+	num_banks >>= LLCC_LB_CNT_SHIFT;
+	drv_data->no_banks = num_banks;
+
+	rc = of_property_read_u32(pdev->dev.of_node, "max-slices",
+				  &drv_data->max_slices);
+	if (rc) {
+		dev_err(&pdev->dev, "Invalid max-slices dt entry\n");
+		devm_kfree(&pdev->dev, drv_data);
+		return rc;
+	}
+
+	rc = of_property_read_u32(pdev->dev.parent->of_node,
+			"qcom,llcc-broadcast-off", &drv_data->b_off);
+	if (rc) {
+		dev_err(&pdev->dev, "Invalid qcom,broadcast-off entry\n");
+		devm_kfree(&pdev->dev, drv_data);
+		return rc;
+	}
+
+	drv_data->llcc_slice_map = kcalloc(BITS_TO_LONGS(drv_data->max_slices),
+				   sizeof(unsigned long), GFP_KERNEL);
+
+	if (!drv_data->llcc_slice_map) {
+		devm_kfree(&pdev->dev, drv_data);
+		return PTR_ERR(drv_data->llcc_slice_map);
+	}
+
+	bitmap_zero(drv_data->llcc_slice_map, drv_data->max_slices);
+	drv_data->slice_data = llcc_cfg;
+	drv_data->llcc_config_data_sz = sz;
+	mutex_init(&drv_data->slice_mutex);
+	platform_set_drvdata(pdev, drv_data);
+
+	qcom_llcc_cfg_program(pdev);
+
+	return rc;
+}
+EXPORT_SYMBOL(qcom_llcc_probe);
+
+int qcom_llcc_remove(struct platform_device *pdev)
+{
+	static struct llcc_drv_data *drv_data;
+
+	drv_data = platform_get_drvdata(pdev);
+
+	mutex_destroy(&drv_data->slice_mutex);
+	kfree(drv_data->llcc_slice_map);
+	devm_kfree(&pdev->dev, drv_data);
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+EXPORT_SYMBOL(qcom_llcc_remove);
diff --git a/include/linux/soc/qcom/llcc-qcom.h b/include/linux/soc/qcom/llcc-qcom.h
new file mode 100644
index 0000000..14bd7e7
--- /dev/null
+++ b/include/linux/soc/qcom/llcc-qcom.h
@@ -0,0 +1,152 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LLCC_QCOM__
+#define __LLCC_QCOM__
+
+/**
+ * llcc_slice_desc - Cache slice descriptor
+ * @llcc_slice_id: llcc slice id
+ * @llcc_slice_size: Size allocated for the llcc slice
+ * @dev: pointer to llcc device
+ */
+struct llcc_slice_desc {
+	int llcc_slice_id;
+	size_t llcc_slice_size;
+	struct device *dev;
+};
+
+/**
+ * llcc_slice_config - Data associated with the llcc slice
+ * @name: name of the use case associated with the llcc slice
+ * @usecase_id: usecase id for which the llcc slice is used
+ * @slice_id: llcc slice id assigned to each slice
+ * @max_cap: maximum capacity of the llcc slice
+ * @priority: priority of the llcc slice
+ * @fixed_size: whether the llcc slice can grow beyond its size
+ * @bonus_ways: bonus ways associated with llcc slice
+ * @res_ways: reserved ways associated with llcc slice
+ * @cache_mode: mode of the llcce slice
+ * @probe_target_ways: Probe only reserved and bonus ways on a cache miss
+ * @dis_cap_alloc: Disable capacity based allocation
+ * @retain_on_pc: Retain through power collapse
+ * @activate_on_init: activate the slice on init
+ */
+struct llcc_slice_config {
+	const char *name;
+	int usecase_id;
+	int slice_id;
+	u32 max_cap;
+	u32 priority;
+	bool fixed_size;
+	u32 bonus_ways;
+	u32 res_ways;
+	u32 cache_mode;
+	u32 probe_target_ways;
+	bool dis_cap_alloc;
+	bool retain_on_pc;
+	u32 activate_on_init;
+};
+
+#ifdef CONFIG_QCOM_LLCC
+/**
+ * llcc_slice_getd - get llcc slice descriptor
+ * @dev: Device pointer of the client
+ * @name: Name of the use case
+ */
+struct llcc_slice_desc *llcc_slice_getd(struct device *dev, const char *name);
+
+/**
+ * llcc_slice_putd - llcc slice descritpor
+ * @desc: Pointer to llcc slice descriptor
+ */
+void llcc_slice_putd(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_get_slice_id - get slice id
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_get_slice_id(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_get_slice_size - llcc slice size
+ * @desc: Pointer to llcc slice descriptor
+ */
+size_t llcc_get_slice_size(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_slice_activate - Activate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_slice_activate(struct llcc_slice_desc *desc);
+
+/**
+ * llcc_slice_deactivate - Deactivate the llcc slice
+ * @desc: Pointer to llcc slice descriptor
+ */
+int llcc_slice_deactivate(struct llcc_slice_desc *desc);
+
+/**
+ * qcom_llcc_probe - program the sct table
+ * @pdev: platform device pointer
+ * @table: soc sct table
+ */
+int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *table, u32 sz);
+/**
+ * qcom_llcc_remove - clean up llcc driver
+ * @pdev: platform driver pointer
+ */
+int qcom_llcc_remove(struct platform_device *pdev);
+#else
+static inline struct llcc_slice_desc *llcc_slice_getd(struct device *dev,
+			const char *name)
+{
+	return NULL;
+}
+
+static inline void llcc_slice_putd(struct llcc_slice_desc *desc)
+{
+
+};
+
+static inline int llcc_get_slice_id(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+
+static inline size_t llcc_get_slice_size(struct llcc_slice_desc *desc)
+{
+	return 0;
+}
+static inline int llcc_slice_activate(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+
+static inline int llcc_slice_deactivate(struct llcc_slice_desc *desc)
+{
+	return -EINVAL;
+}
+static inline int qcom_llcc_probe(struct platform_device *pdev,
+		      const struct llcc_slice_config *table, u32 sz)
+{
+	return -ENODEV;
+}
+
+static inline int qcom_llcc_remove(struct platform_device *pdev)
+{
+	return -ENODEV;
+}
+#endif
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2018-03-23 23:57 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-25 23:55 [PATCH 0/2] SDM845 System Cache Driver Channagoud Kadabi
2018-01-25 23:55 ` [PATCH 1/2] dt-bindings: Documentation for qcom,llcc Channagoud Kadabi
2018-02-01 10:44   ` Mark Rutland
2018-02-01 20:39     ` Channa
2018-02-02 11:05       ` Mark Rutland
2018-02-06 19:56         ` Channa
2018-02-13 14:37           ` Mark Rutland
2018-02-13 17:38             ` Channa
2018-02-01 10:48   ` Mark Rutland
2018-02-01 20:47     ` Channa
2018-02-02 11:08       ` Mark Rutland
2018-02-08 16:52   ` Matt Sealey
2018-02-09  0:24     ` Channa
2018-02-13 14:33       ` Mark Rutland
2018-01-25 23:55 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
2018-03-19 14:55   ` Jordan Crouse
2018-03-23 23:57     ` Channa
  -- strict thread matches above, loose matches on Subject: below --
2018-01-16 22:35 [PATCH 0/2] SDM845 System Cache Driver Channagoud Kadabi
2018-01-16 22:35 ` [PATCH 2/2] drivers: soc: Add LLCC driver Channagoud Kadabi
2018-01-25 23:39   ` Trilok Soni
2018-01-30  1:57   ` kbuild test robot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).