2019-04-04 17:23:20

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 0/8] Exynos Adaptive Supply Voltage support

The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
subsystem operating points, i.e. power supply voltage for given clock
frequency, in order to better match actual capabilities of the hardware
and optimize power consumption. This applies to subsystems of the SoC like:
CPU clusters, GPU, the memory controller or camera ISP. During production
process the SoC chip is assigned to one of several bins (ASV groups) and
the group information is encoded in the SoC CHIPID block registers and/or
OTP memory. This information is then used to select more finely matching
operating points for devices.

The motivation of this patch set was, amongst others, to ensure proper
Odroid XU3/XU4 operation with highest performance operating points.

This patch set adds a driver parsing ASV tables from DT and finely
adjusting CPU operating points to optimize power consumption and ensure
proper operation for each SoC revision.

I just recently noticed there are already somewhat similar drivers located
in drivers/power/avs, I'm considering moving exynos-asv driver there in next
iteration of this patch set.

This patch set includes Exynos CHIPID driver posted by Pankaj Dubey and
futher improved by Bartlomiej Zolnierkiewicz [1].

Tested on Odroid XU3, XU3 Lite, XU4 and Exynos5433 TM2 board (with further
patches not included in this series).

The DT binding documented in patch 3/8 doesn't describe any hardware,
it's purely software description. I'd like to get some feedback specially
on that one, I thought it was reasonable to put that data in DT. There
will be many of this tables, per each SoC type and the driver looks much
better with those tables in DT IMHO.

[1] https://lkml.org/lkml/2018/11/15/908

Pankaj Dubey (3):
soc: samsung: Add exynos chipid driver support
ARM: EXYNOS: enable exynos_chipid for ARCH_EXYNOS
ARM64: EXYNOS: enable exynos_chipid for ARCH_EXYNOS

Sylwester Nawrocki (5):
soc: samsung: Exynos chipid driver update
dt-bindings: exynos: Add ASV tables binding documentation
soc: samsung: Add Exynos Adaptive Supply Voltage driver
ARM: EXYNOS: Enable exynos-asv driver for ARCH_EXYNOS
ARM: dts: exynos: Add ASV tables for exynos5422/5800

.../devicetree/bindings/arm/samsung/asv.txt | 76 +++++
arch/arm/boot/dts/exynos5.dtsi | 2 +-
arch/arm/boot/dts/exynos5800.dtsi | 207 +++++++++++++
arch/arm/mach-exynos/Kconfig | 2 +
arch/arm64/Kconfig.platforms | 1 +
drivers/soc/samsung/Kconfig | 16 +
drivers/soc/samsung/Makefile | 5 +
drivers/soc/samsung/exynos-asv.c | 279 ++++++++++++++++++
drivers/soc/samsung/exynos-asv.h | 114 +++++++
drivers/soc/samsung/exynos-chipid.c | 113 +++++++
drivers/soc/samsung/exynos-chipid.h | 48 +++
drivers/soc/samsung/exynos5422-asv.c | 209 +++++++++++++
drivers/soc/samsung/exynos5422-asv.h | 25 ++
13 files changed, 1096 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/arm/samsung/asv.txt
create mode 100644 drivers/soc/samsung/exynos-asv.c
create mode 100644 drivers/soc/samsung/exynos-asv.h
create mode 100644 drivers/soc/samsung/exynos-chipid.c
create mode 100644 drivers/soc/samsung/exynos-chipid.h
create mode 100644 drivers/soc/samsung/exynos5422-asv.c
create mode 100644 drivers/soc/samsung/exynos5422-asv.h

--
2.17.1


2019-04-04 17:23:24

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 1/8] soc: samsung: Add exynos chipid driver support

From: Pankaj Dubey <[email protected]>

Exynos SoCs have Chipid, for identification of product IDs and SoC
revisions. This patch intends to provide initialization code for all
these functionalities, at the same time it provides some sysfs entries
for accessing these information to user-space.

This driver uses existing binding for exynos-chipid.

Changes by Bartlomiej:
- fixed return values on errors
- removed bogus kfree_const()
- added missing Exynos4210 EVT0 id
- converted code to use EXYNOS_MASK define
- fixed np use after of_node_put()
- fixed too early use of dev_info()
- made driver fail for unknown SoC-s
- added SPDX tag
- updated Copyrights

Signed-off-by: Pankaj Dubey <[email protected]>
[m.szyprowski: for suggestion and code snippet of product_id_to_soc_id]
Signed-off-by: Marek Szyprowski <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
---
drivers/soc/samsung/Kconfig | 5 ++
drivers/soc/samsung/Makefile | 2 +
drivers/soc/samsung/exynos-chipid.c | 111 ++++++++++++++++++++++++++++
3 files changed, 118 insertions(+)
create mode 100644 drivers/soc/samsung/exynos-chipid.c

diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index 2186285fda92..2905f5262197 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -7,6 +7,11 @@ menuconfig SOC_SAMSUNG

if SOC_SAMSUNG

+config EXYNOS_CHIPID
+ bool "Exynos Chipid controller driver" if COMPILE_TEST
+ depends on ARCH_EXYNOS || COMPILE_TEST
+ select SOC_BUS
+
config EXYNOS_PMU
bool "Exynos PMU controller driver" if COMPILE_TEST
depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index 29f294baac6e..3b6a8797416c 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,4 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o

obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
new file mode 100644
index 000000000000..5cb018807817
--- /dev/null
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS - CHIP ID support
+ * Author: Pankaj Dubey <[email protected]>
+ * Author: Bartlomiej Zolnierkiewicz <[email protected]>
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#define EXYNOS_SUBREV_MASK (0xF << 4)
+#define EXYNOS_MAINREV_MASK (0xF << 0)
+#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
+#define EXYNOS_MASK 0xFFFFF000
+
+static const struct exynos_soc_id {
+ const char *name;
+ unsigned int id;
+} soc_ids[] = {
+ { "EXYNOS3250", 0xE3472000 },
+ { "EXYNOS4210", 0x43200000 }, /* EVT0 revision */
+ { "EXYNOS4210", 0x43210000 },
+ { "EXYNOS4212", 0x43220000 },
+ { "EXYNOS4412", 0xE4412000 },
+ { "EXYNOS5250", 0x43520000 },
+ { "EXYNOS5260", 0xE5260000 },
+ { "EXYNOS5410", 0xE5410000 },
+ { "EXYNOS5420", 0xE5420000 },
+ { "EXYNOS5440", 0xE5440000 },
+ { "EXYNOS5800", 0xE5422000 },
+ { "EXYNOS7420", 0xE7420000 },
+ { "EXYNOS5433", 0xE5433000 },
+};
+
+static const char * __init product_id_to_soc_id(unsigned int product_id)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(soc_ids); i++)
+ if ((product_id & EXYNOS_MASK) == soc_ids[i].id)
+ return soc_ids[i].name;
+ return NULL;
+}
+
+int __init exynos_chipid_early_init(void)
+{
+ struct soc_device_attribute *soc_dev_attr;
+ void __iomem *exynos_chipid_base;
+ struct soc_device *soc_dev;
+ struct device_node *root;
+ struct device_node *np;
+ u32 product_id;
+ u32 revision;
+
+ /* look up for chipid node */
+ np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
+ if (!np)
+ return -ENODEV;
+
+ exynos_chipid_base = of_iomap(np, 0);
+ of_node_put(np);
+
+ if (!exynos_chipid_base) {
+ pr_err("Failed to map SoC chipid\n");
+ return -ENXIO;
+ }
+
+ product_id = readl_relaxed(exynos_chipid_base);
+ revision = product_id & EXYNOS_REV_MASK;
+ iounmap(exynos_chipid_base);
+
+ soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ if (!soc_dev_attr)
+ return -ENOMEM;
+
+ soc_dev_attr->family = "Samsung Exynos";
+
+ root = of_find_node_by_path("/");
+ of_property_read_string(root, "model", &soc_dev_attr->machine);
+ of_node_put(root);
+
+ soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision);
+ soc_dev_attr->soc_id = product_id_to_soc_id(product_id);
+ if (!soc_dev_attr->soc_id) {
+ pr_err("Unknown SoC\n");
+ return -ENODEV;
+ }
+
+ /* please note that the actual registration will be deferred */
+ soc_dev = soc_device_register(soc_dev_attr);
+ if (IS_ERR(soc_dev)) {
+ kfree(soc_dev_attr->revision);
+ kfree(soc_dev_attr);
+ return PTR_ERR(soc_dev);
+ }
+
+ /* it is too early to use dev_info() here (soc_dev is NULL) */
+ pr_info("soc soc0: Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
+ soc_dev_attr->soc_id, product_id, revision);
+
+ return 0;
+}
+early_initcall(exynos_chipid_early_init);
--
2.17.1

2019-04-04 17:23:42

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 2/8] soc: samsung: Exynos chipid driver update

This patch adds definition of selected CHIP ID register offsets
and register bit field definitions for Exynos5422 SoC.

exynos_chipid_read() helper function is added to allow reading
the CHIP ID block registers.

Signed-off-by: Sylwester Nawrocki <[email protected]>
---
drivers/soc/samsung/exynos-chipid.c | 16 +++++-----
drivers/soc/samsung/exynos-chipid.h | 48 +++++++++++++++++++++++++++++
2 files changed, 57 insertions(+), 7 deletions(-)
create mode 100644 drivers/soc/samsung/exynos-chipid.h

diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
index 5cb018807817..4920f0ef2c55 100644
--- a/drivers/soc/samsung/exynos-chipid.c
+++ b/drivers/soc/samsung/exynos-chipid.c
@@ -16,10 +16,7 @@
#include <linux/slab.h>
#include <linux/sys_soc.h>

-#define EXYNOS_SUBREV_MASK (0xF << 4)
-#define EXYNOS_MAINREV_MASK (0xF << 0)
-#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
-#define EXYNOS_MASK 0xFFFFF000
+#include "exynos-chipid.h"

static const struct exynos_soc_id {
const char *name;
@@ -40,6 +37,13 @@ static const struct exynos_soc_id {
{ "EXYNOS5433", 0xE5433000 },
};

+static void __iomem *exynos_chipid_base;
+
+unsigned int exynos_chipid_read(unsigned int offset)
+{
+ return readl_relaxed(exynos_chipid_base + offset);
+}
+
static const char * __init product_id_to_soc_id(unsigned int product_id)
{
int i;
@@ -53,7 +57,6 @@ static const char * __init product_id_to_soc_id(unsigned int product_id)
int __init exynos_chipid_early_init(void)
{
struct soc_device_attribute *soc_dev_attr;
- void __iomem *exynos_chipid_base;
struct soc_device *soc_dev;
struct device_node *root;
struct device_node *np;
@@ -73,9 +76,8 @@ int __init exynos_chipid_early_init(void)
return -ENXIO;
}

- product_id = readl_relaxed(exynos_chipid_base);
+ product_id = exynos_chipid_read(EXYNOS_CHIPID_REG_PRO_ID);
revision = product_id & EXYNOS_REV_MASK;
- iounmap(exynos_chipid_base);

soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
diff --git a/drivers/soc/samsung/exynos-chipid.h b/drivers/soc/samsung/exynos-chipid.h
new file mode 100644
index 000000000000..826a12c25fa2
--- /dev/null
+++ b/drivers/soc/samsung/exynos-chipid.h
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * EXYNOS - CHIP ID support
+ */
+
+#define EXYNOS_CHIPID_REG_PRO_ID 0x00
+ #define EXYNOS_SUBREV_MASK (0xf << 4)
+ #define EXYNOS_MAINREV_MASK (0xf << 0)
+ #define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \
+ EXYNOS_MAINREV_MASK)
+ #define EXYNOS_MASK 0xfffff000
+
+#define EXYNOS_CHIPID_REG_PKG_ID 0x04
+ #define EXYNOS5422_IDS_OFFSET 24
+ #define EXYNOS5422_IDS_MASK 0xff
+ #define EXYNOS5422_USESG_OFFSET 3
+ #define EXYNOS5422_USESG_MASK 0x01
+ #define EXYNOS5422_SG_OFFSET 0
+ #define EXYNOS5422_SG_MASK 0x07
+ #define EXYNOS5422_TABLE_OFFSET 8
+ #define EXYNOS5422_TABLE_MASK 0x03
+ #define EXYNOS5422_SG_A_OFFSET 17
+ #define EXYNOS5422_SG_A_MASK 0x0f
+ #define EXYNOS5422_SG_B_OFFSET 21
+ #define EXYNOS5422_SG_B_MASK 0x03
+ #define EXYNOS5422_SG_BSIGN_OFFSET 23
+ #define EXYNOS5422_SG_BSIGN_MASK 0x01
+ #define EXYNOS5422_BIN2_OFFSET 12
+ #define EXYNOS5422_BIN2_MASK 0x01
+
+#define EXYNOS_CHIPID_REG_LOT_ID 0x14
+
+#define EXYNOS_CHIPID_AUX_INFO 0x1c
+ #define EXYNOS5422_TMCB_OFFSET 0
+ #define EXYNOS5422_TMCB_MASK 0x7f
+ #define EXYNOS5422_ARM_UP_OFFSET 8
+ #define EXYNOS5422_ARM_UP_MASK 0x03
+ #define EXYNOS5422_ARM_DN_OFFSET 10
+ #define EXYNOS5422_ARM_DN_MASK 0x03
+ #define EXYNOS5422_KFC_UP_OFFSET 12
+ #define EXYNOS5422_KFC_UP_MASK 0x03
+ #define EXYNOS5422_KFC_DN_OFFSET 14
+ #define EXYNOS5422_KFC_DN_MASK 0x03
+
+unsigned int exynos_chipid_read(unsigned int offset);
--
2.17.1

2019-04-04 17:23:44

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 3/8] dt-bindings: exynos: Add ASV tables binding documentation

This patch adds documentation of the Exynos ASV (Adaptive Voltage Supply)
tables DT binding.

Signed-off-by: Sylwester Nawrocki <[email protected]>
---
.../devicetree/bindings/arm/samsung/asv.txt | 76 +++++++++++++++++++
1 file changed, 76 insertions(+)
create mode 100644 Documentation/devicetree/bindings/arm/samsung/asv.txt

diff --git a/Documentation/devicetree/bindings/arm/samsung/asv.txt b/Documentation/devicetree/bindings/arm/samsung/asv.txt
new file mode 100644
index 000000000000..0db907263a91
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/samsung/asv.txt
@@ -0,0 +1,76 @@
+Exynos Adaptive Supply Voltage (ASV) tables
+-------------------------------------------
+
+The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
+operating points, i.e. the power supply voltage for given clock frequency,
+in order to better match actual capabilities of the hardware and optimize power
+consumption. This applies to subsystem of the SoC like: CPU clusters, GPU,
+the memory controller or camera ISP. During production process the SoC chip
+is assigned to one of several bins (ASV groups) and the group information
+is encoded in the SoC CHIPID block registers and/or OTP memory. This information
+is then used by the OS to select more finely matching operating points for
+devices.
+
+This binding describes data used to create actual operating points for the
+subsystems. The data is in form of two-dimensional arrays of M x N cells,
+where the first column contains frequency values and subsequent columns
+associated with ASV groups contain corresponding voltage values.
+
+ frequency group0 group1 ... group(N-1)
+ 0 1 2 ... N-1
+0 <f0 V00 V01 ... V0n>,
+1 <f1 V10 V11 ... V1n>,
+... < ... >,
+M-1 <fm Vm0 Vm1 ... Vmn>,
+
+In simplest form the actual operating points set may be created by selecting
+whole column for the voltage values, however also parts of multiple columns may
+be combined by the OS to create series of voltage values corresponding to
+frequencies in column 0.
+
+The ASV tables are defined as sub-nodes of parent node containing all tables.
+
+* Main node
+
+Required properties:
+ - compatible : should at least contain "samsung,exynos-asv-v1".
+
+* Table node
+
+Required properties:
+ - samsung,asv-table-size : specifies dimension of the table, the first cell is
+ total number of rows (M), the second cell is total number of columns (N),
+ - samsung,asv-table-id : ID of the table, lower 8-bits is an index (revision)
+ of the table, remaining bits (31...8) specify a subsystem the table applies
+ to: 0 - ARM/Eagle (big) CPU cluster, 1 - KFC (little) CPU cluster,
+ - samsung,asv-data : the ASV table data as described earlier in this document.
+ First cell is frequency value, then N-1 voltage values. Such sequence
+ is repeated M times.
+
+Optional properties:
+ - samsung,asv-common-data : a list of frequency, voltage pairs used to describe
+ operating points where voltage is same for all N-1 ASV groups. This allows
+ to avoid data duplication is the "samsung,asv-data" property.
+
+Example:
+
+&chipid {
+ asv {
+ compatible = "samsung,exynos-asv-v1";
+ asv-table-0 {
+ samsung,asv-table-size = <8 6>;
+ samsung,asv-table-id = <0x0>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 */
+ <1700 1187500 1175000 1162500 1150000 1137500 >,
+ <1500 1125000 1112500 1100000 1087500 1075000 >,
+ <1300 1075000 1062500 1050000 1037500 1025000 >,
+ <1000 987500 975000 962500 950000 937500 >,
+ < 900 950000 937500 925000 925000 925000 >,
+ < 700 925000 912500 912500 912500 912500 >;
+ /* ASV0...15 */
+ samsung,asv-common-data = <600 900000>,
+ <500 900000>;
+ };
+ };
+};
--
2.17.1

2019-04-04 17:23:49

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 4/8] soc: samsung: Add Exynos Adaptive Supply Voltage driver

The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
operating points of devices in order to better match actual capabilities
of the hardware and optimize power consumption.

This patch adds common code for parsing the ASV tables from devicetree
and updating CPU OPPs.

Also support for Exynos5422/5800 SoC is added, the Exynos5422 specific part
of the patch is partially based on code from
https://github.com/hardkernel/linux repository, branch odroidxu4-4.14.y,
files: arch/arm/mach-exynos/exynos5422-asv.[ch].

Tested on Odroid XU3, XU4, XU3 Lite.

Signed-off-by: Sylwester Nawrocki <[email protected]>
---
drivers/soc/samsung/Kconfig | 11 ++
drivers/soc/samsung/Makefile | 3 +
drivers/soc/samsung/exynos-asv.c | 279 +++++++++++++++++++++++++++
drivers/soc/samsung/exynos-asv.h | 114 +++++++++++
drivers/soc/samsung/exynos5422-asv.c | 209 ++++++++++++++++++++
drivers/soc/samsung/exynos5422-asv.h | 25 +++
6 files changed, 641 insertions(+)
create mode 100644 drivers/soc/samsung/exynos-asv.c
create mode 100644 drivers/soc/samsung/exynos-asv.h
create mode 100644 drivers/soc/samsung/exynos5422-asv.c
create mode 100644 drivers/soc/samsung/exynos5422-asv.h

diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
index 2905f5262197..4d121984f71a 100644
--- a/drivers/soc/samsung/Kconfig
+++ b/drivers/soc/samsung/Kconfig
@@ -7,6 +7,17 @@ menuconfig SOC_SAMSUNG

if SOC_SAMSUNG

+config EXYNOS_ASV
+ bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST
+ depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
+ depends on EXYNOS_CHIPID
+ select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS
+
+# There is no need to enable these drivers for ARMv8
+config EXYNOS_ASV_ARM
+ bool "Exynos ASV ARMv7-specific driver extensions" if COMPILE_TEST
+ depends on EXYNOS_ASV
+
config EXYNOS_CHIPID
bool "Exynos Chipid controller driver" if COMPILE_TEST
depends on ARCH_EXYNOS || COMPILE_TEST
diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
index 3b6a8797416c..edd1d6ea064d 100644
--- a/drivers/soc/samsung/Makefile
+++ b/drivers/soc/samsung/Makefile
@@ -1,5 +1,8 @@
# SPDX-License-Identifier: GPL-2.0

+obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o
+obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o
+
obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o

diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
new file mode 100644
index 000000000000..60532c7eb3aa
--- /dev/null
+++ b/drivers/soc/samsung/exynos-asv.c
@@ -0,0 +1,279 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ * Author: Sylwester Nawrocki <[email protected]>
+ *
+ * Samsung Exynos SoC Adaptive Supply Voltage support
+ */
+
+#include <linux/cpu.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+
+#include "exynos-asv.h"
+#include "exynos5422-asv.h"
+#include "exynos5433-asv.h"
+
+#ifndef MHZ
+#define MHZ 1000000U
+#endif
+
+static struct exynos_asv *exynos_asv;
+
+int exynos_asv_parse_of_table(struct device_node *node,
+ struct exynos_asv_table *table,
+ int index)
+{
+ u32 table_size, table_id = 0;
+ unsigned int len1, len2 = 0;
+ unsigned int num_cols, num_rows;
+ u32 tmp[20];
+ u32 *buf;
+ int ret;
+
+ ret = of_property_read_u32(node, "samsung,asv-table-id",
+ &table_id);
+ if (ret < 0) {
+ pr_err("ASV: Missing table id in %pOF\n", node);
+ return ret;
+ }
+ table->id = table_id;
+
+ if (index >= 0 && asv_table_to_index(table_id) != index)
+ return -EBADR;
+
+ ret = of_property_read_u32_array(node, "samsung,asv-table-size",
+ tmp, 2);
+ if (ret < 0)
+ return ret;
+
+ num_rows = tmp[0];
+ num_cols = tmp[1];
+ if (num_rows > EXYNOS_ASV_MAX_LEVELS ||
+ num_cols > (EXYNOS_ASV_MAX_GROUPS + 1)) {
+ pr_err("ASV: Unsupported ASV table size (%d x %d)\n",
+ num_rows, num_cols);
+ return -EINVAL;
+ }
+
+ table_size = num_rows * num_cols;
+ buf = kcalloc(table_size, sizeof(u32), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = of_property_read_variable_u32_array(node, "samsung,asv-data",
+ buf, 0, table_size);
+ if (ret < 0)
+ goto err_free_buf;
+
+ len1 = ret;
+
+ if (ret < table_size) {
+ u32 *dst, *src;
+ ret = of_property_read_variable_u32_array(node,
+ "samsung,asv-common-data",
+ (u32 *)tmp, 0,
+ ARRAY_SIZE(tmp));
+ if (ret < 0) {
+ pr_err("ASV: Not enough data for table #%x (%d x %d)\n",
+ table_id, num_rows, num_cols);
+ goto err_free_buf;
+ }
+ len2 = ret;
+
+ if (len1 + ((len2 / 2) * num_cols) > table_size) {
+ pr_err("ASV: Incorrect table %#x definition\n",
+ table_id);
+ ret = -EINVAL;
+ goto err_free_buf;
+ }
+ /*
+ * Copy data common to all ASV levels to first and second column
+ * in the main buffer. We don't replicate data to further
+ * columns, instead they are left initialized to 0 (invalid,
+ * unused frequency value). We assume that users of the table
+ * will refer to voltage data in column 1 if 0 is encountered
+ * in any further column (2, 3,...).
+ */
+ dst = buf + len1;
+ src = tmp;
+
+ while (len2 >= 2) {
+ memcpy(dst, src, 2 * sizeof(u32));
+ dst += num_cols;
+ src += 2;
+ len2 -= 2;
+ }
+ }
+
+ table->num_cols = num_cols;
+ table->num_rows = num_rows;
+ table->buf = buf;
+ return 0;
+
+err_free_buf:
+ kfree(buf);
+ return ret;
+}
+
+int exynos_asv_parse_cpu_tables(struct exynos_asv *asv, struct device_node *np,
+ int table_index)
+{
+ struct exynos_asv_subsys *subsys;
+ struct exynos_asv_table table;
+ struct device_node *child;
+ int ret;
+
+ for_each_child_of_node(np, child) {
+ ret = exynos_asv_parse_of_table(child, &table, table_index);
+ if (ret < 0) {
+ if (ret == -EBADR)
+ continue;
+ of_node_put(child);
+ return ret;
+ }
+
+ pr_debug("%s: Matching table: id: %#x at %pOF\n",
+ __func__, table.id, child);
+
+ switch(asv_table_to_subsys_id(table.id)) {
+ case EXYNOS_ASV_SUBSYS_ID_ARM:
+ subsys = &asv->arm;
+ break;
+ case EXYNOS_ASV_SUBSYS_ID_KFC:
+ subsys = &asv->kfc;
+ break;
+ default:
+ of_node_put(child);
+ return -EINVAL;
+ }
+
+ subsys->num_asv_levels = table.num_rows;
+ subsys->num_asv_groups = table.num_cols - 1;
+ subsys->table = table;
+ subsys->id = asv_table_to_subsys_id(table.id);
+ }
+
+ return 0;
+}
+
+static int exynos_asv_update_cpu_opps(struct device *cpu)
+{
+ struct exynos_asv_subsys *subsys = NULL;
+ struct dev_pm_opp *opp;
+ unsigned int opp_freq;
+ int i;
+
+ if (of_device_is_compatible(cpu->of_node,
+ exynos_asv->arm.cpu_dt_compat))
+ subsys = &exynos_asv->arm;
+ else if (of_device_is_compatible(cpu->of_node,
+ exynos_asv->kfc.cpu_dt_compat))
+ subsys = &exynos_asv->kfc;
+
+ if (!subsys)
+ return -EINVAL;
+
+ for (i = 0; i < subsys->num_asv_levels; i++) {
+ unsigned int new_voltage;
+ unsigned int voltage;
+ int timeout = 1000;
+ int err;
+
+ opp_freq = exynos_asv_opp_get_frequency(subsys, i);
+
+ opp = dev_pm_opp_find_freq_exact(cpu, opp_freq * MHZ, true);
+ if (IS_ERR(opp)) {
+ pr_info("%s cpu%d opp%d, freq: %u missing\n",
+ __func__, cpu->id, i, opp_freq);
+
+ continue;
+ }
+
+ voltage = dev_pm_opp_get_voltage(opp);
+ new_voltage = exynos_asv->opp_get_voltage(subsys, i, voltage);
+ dev_pm_opp_put(opp);
+
+ opp_freq *= MHZ;
+ dev_pm_opp_remove(cpu, opp_freq);
+
+ while (--timeout) {
+ opp = dev_pm_opp_find_freq_exact(cpu, opp_freq, true);
+ if (IS_ERR(opp))
+ break;
+ dev_pm_opp_put(opp);
+ msleep(1);
+ }
+
+ err = dev_pm_opp_add(cpu, opp_freq, new_voltage);
+ if (err < 0)
+ pr_err("%s: Failed to add OPP %u Hz/%u uV for cpu%d\n",
+ __func__, opp_freq, new_voltage, cpu->id);
+ }
+
+ return 0;
+}
+
+static int exynos_asv_update_opps(void)
+{
+ struct opp_table *last_opp_table = NULL;
+ struct device *cpu;
+ int ret, cpuid;
+
+ for_each_possible_cpu(cpuid) {
+ struct opp_table *opp_table;
+
+ cpu = get_cpu_device(cpuid);
+ if (!cpu)
+ continue;
+
+ opp_table = dev_pm_opp_get_opp_table(cpu);
+ if (IS_ERR(opp_table))
+ continue;
+
+ if (!last_opp_table || opp_table != last_opp_table) {
+ last_opp_table = opp_table;
+
+ ret = exynos_asv_update_cpu_opps(cpu);
+ if (ret < 0)
+ pr_err("%s: Couldn't udate OPPs for cpu%d\n",
+ __func__, cpuid);
+ }
+
+ dev_pm_opp_put_opp_table(opp_table);
+ }
+
+ return 0;
+}
+
+static int __init exynos_asv_init(void)
+{
+ int ret;
+
+ exynos_asv = kcalloc(1, sizeof(struct exynos_asv), GFP_KERNEL);
+ if (!exynos_asv)
+ return -ENOMEM;
+
+ if (of_machine_is_compatible("samsung,exynos5800") ||
+ of_machine_is_compatible("samsung,exynos5420"))
+ ret = exynos5422_asv_init(exynos_asv);
+ else
+ return 0;
+
+ if (ret < 0)
+ return ret;
+
+ ret = exynos_asv_update_opps();
+
+ if (exynos_asv->release)
+ exynos_asv->release(exynos_asv);
+
+ return ret;
+}
+late_initcall(exynos_asv_init)
diff --git a/drivers/soc/samsung/exynos-asv.h b/drivers/soc/samsung/exynos-asv.h
new file mode 100644
index 000000000000..3444b361e5e3
--- /dev/null
+++ b/drivers/soc/samsung/exynos-asv.h
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ * Author: Sylwester Nawrocki <[email protected]>
+ *
+ * Samsung Exynos SoC Adaptive Supply Voltage support
+ */
+#ifndef __EXYNOS_ASV_H
+#define __EXYNOS_ASV_H
+
+#define EXYNOS_ASV_MAX_GROUPS 16
+#define EXYNOS_ASV_MAX_LEVELS 24
+
+#define EXYNOS_ASV_TABLE_INDEX_MASK (0xff)
+#define EXYNOS_ASV_SUBSYS_ID_MASK (0xff << 8)
+
+#define asv_table_to_subsys_id(_id) ((_id >> 8) & 0xff)
+#define asv_table_to_index(_id) ((_id) & 0xff)
+
+#define EXYNOS_ASV_SUBSYS_ID_ARM 0x0
+#define EXYNOS_ASV_SUBSYS_ID_EGL EXYNOS_ASV_SUBSYS_ID_ARM
+#define EXYNOS_ASV_SUBSYS_ID_KFC 0x1
+#define EXYNOS_ASV_SUBSYS_ID_INT 0x2
+#define EXYNOS_ASV_SUBSYS_ID_MIF 0x3
+#define EXYNOS_ASV_SUBSYS_ID_G3D 0x4
+#define EXYNOS_ASV_SUBSYS_ID_CAM 0x5
+#define EXYNOS_ASV_SUBSYS_ID_MAX 0x6
+
+struct device_node;
+
+/* HPM, IDS values to select target group */
+struct asv_limit_entry {
+ unsigned int hpm;
+ unsigned int ids;
+};
+
+struct exynos_asv_table {
+ unsigned int num_rows;
+ unsigned int num_cols;
+ unsigned int id;
+ u32 *buf;
+};
+
+struct exynos_asv_subsys {
+ int id;
+ char *cpu_dt_compat;
+
+ unsigned int base_volt;
+ unsigned int num_asv_levels;
+ unsigned int num_asv_groups;
+ unsigned int offset_volt_h;
+ unsigned int offset_volt_l;
+ struct exynos_asv_table table;
+};
+
+struct exynos_asv {
+ struct device_node *chipid_node;
+ struct exynos_asv_subsys arm;
+ struct exynos_asv_subsys kfc;
+
+ int (*opp_get_voltage)(struct exynos_asv_subsys *subs, int level,
+ unsigned int voltage);
+ void (*release)(struct exynos_asv *asv);
+
+ unsigned int group;
+ unsigned int table;
+
+ /* TODO: Move member fields below to SoC type specific data structure */
+ unsigned int is_bin2;
+ unsigned int is_special_lot;
+};
+
+static inline u32 __exynos_asv_get_item(struct exynos_asv_table *table,
+ unsigned int row, unsigned int col)
+{
+ return table->buf[row * (table->num_cols) + col];
+}
+
+static inline u32 exynos_asv_opp_get_frequency(struct exynos_asv_subsys *subsys,
+ unsigned int index)
+{
+ return __exynos_asv_get_item(&subsys->table, index, 0);
+}
+/**
+ * exynos_asv_parse_of_table - Parse ASV table from devicetree
+ *
+ * @node: DT node containing the table
+ * @table: The parsed table data
+ * @index: Used to select table with specific index to parse, if >= 0.
+ * This argument is ignored if the value is less than 0.
+ *
+ * Returns: 0 on success, or negative value on failure. EBADR is returned
+ * when @index is >= 0 but the index value of the parsed table ID is different
+ * than @index.
+ */
+int exynos_asv_parse_of_table(struct device_node *node,
+ struct exynos_asv_table *table,
+ int index);
+
+/**
+ * exynos_asv_parse_cpu_tables - Parse ARM and KFC ASV tables from DT
+ *
+ * @asv: data structure to store the parsed data to
+ * @node: DT node containing the tables
+ * @index: Used to select table with specific index to parse, if >= 0.
+ * This argument is ignored if the value is less than 0.
+ *
+ * Returns: 0 on success, or negative value on failure.
+ */
+int exynos_asv_parse_cpu_tables(struct exynos_asv *asv, struct device_node *np,
+ int table_index);
+
+#endif /* __EXYNOS_ASV_H */
diff --git a/drivers/soc/samsung/exynos5422-asv.c b/drivers/soc/samsung/exynos5422-asv.c
new file mode 100644
index 000000000000..f0b7bdd873a9
--- /dev/null
+++ b/drivers/soc/samsung/exynos5422-asv.c
@@ -0,0 +1,209 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Samsung Exynos 5422 SoC Adaptive Supply Voltage support
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+
+#include "exynos-asv.h"
+#include "exynos-chipid.h"
+
+#define EXYNOS5422_NUM_ASV_GROUPS 14
+
+static struct exynos_asv *exynos_asv;
+
+static int exynos5422_asv_get_table(void)
+{
+ unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+
+ return (reg >> EXYNOS5422_TABLE_OFFSET) & EXYNOS5422_TABLE_MASK;
+}
+
+static int exynos5422_asv_check_bin2(void)
+{
+ unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+
+ return (reg >> EXYNOS5422_BIN2_OFFSET) & EXYNOS5422_BIN2_MASK;
+}
+
+static bool exynos5422_asv_check_lot_id(void)
+{
+ unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+
+ return ((reg >> EXYNOS5422_USESG_OFFSET) & EXYNOS5422_USESG_MASK);
+}
+
+static const struct asv_limit_entry __asv_limits[EXYNOS5422_NUM_ASV_GROUPS] = {
+ { 13, 55 },
+ { 21, 65 },
+ { 25, 69 },
+ { 30, 72 },
+ { 36, 74 },
+ { 43, 76 },
+ { 51, 78 },
+ { 65, 80 },
+ { 81, 82 },
+ { 98, 84 },
+ { 119, 87 },
+ { 135, 89 },
+ { 150, 92 },
+ { 999, 999 },
+};
+
+static int exynos5422_asv_get_group(struct exynos_asv *asv)
+{
+ unsigned int pkgid_reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
+ unsigned int auxi_reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
+ int hpm, ids, i;
+
+ if (asv->is_special_lot) {
+ u32 sga = (pkgid_reg >> EXYNOS5422_SG_A_OFFSET) &
+ EXYNOS5422_SG_A_MASK;
+
+ u32 sgb = (pkgid_reg >> EXYNOS5422_SG_B_OFFSET) &
+ EXYNOS5422_SG_B_MASK;
+
+ if ((pkgid_reg >> EXYNOS5422_SG_BSIGN_OFFSET) &
+ EXYNOS5422_SG_BSIGN_MASK)
+ return sga + sgb;
+ else
+ return sga - sgb;
+ }
+
+ hpm = (auxi_reg >> EXYNOS5422_TMCB_OFFSET) & EXYNOS5422_TMCB_MASK;
+ ids = (pkgid_reg >> EXYNOS5422_IDS_OFFSET) & EXYNOS5422_IDS_MASK;
+
+ for (i = 0; i < EXYNOS5422_NUM_ASV_GROUPS; i++) {
+ if (ids <= __asv_limits[i].ids)
+ break;
+ if (hpm <= __asv_limits[i].hpm)
+ break;
+ }
+ if (i < EXYNOS5422_NUM_ASV_GROUPS)
+ return i;
+
+ return 0;
+}
+
+static int __asv_offset_voltage(unsigned int index)
+{
+ static const unsigned int offset_table[] = { 12500, 50000, 25000 };
+
+ if (index == 0 || index > 3)
+ return 0;
+
+ return offset_table[index - 1];
+}
+
+static void exynos5422_asv_offset_voltage_setup(struct exynos_asv *asv)
+{
+ struct exynos_asv_subsys *subsys;
+ unsigned int reg, value;
+
+ reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
+
+ /* ARM offset voltage setup */
+ subsys = &asv->arm;
+
+ subsys->base_volt = 1000000;
+
+ value = (reg >> EXYNOS5422_ARM_UP_OFFSET) & EXYNOS5422_ARM_UP_MASK;
+ subsys->offset_volt_h = __asv_offset_voltage(value);
+
+ value = (reg >> EXYNOS5422_ARM_DN_OFFSET) & EXYNOS5422_ARM_DN_MASK;
+ subsys->offset_volt_l = __asv_offset_voltage(value);
+
+ /* KFC offset voltage setup */
+ subsys = &asv->kfc;
+
+ subsys->base_volt = 1000000;
+
+ value = (reg >> EXYNOS5422_KFC_UP_OFFSET) & EXYNOS5422_KFC_UP_MASK;
+ subsys->offset_volt_h = __asv_offset_voltage(value);
+
+ value = (reg >> EXYNOS5422_KFC_DN_OFFSET) & EXYNOS5422_KFC_DN_MASK;
+ subsys->offset_volt_l = __asv_offset_voltage(value);
+}
+
+static int exynos5422_asv_opp_get_voltage(struct exynos_asv_subsys *subsys,
+ int level, unsigned int volt)
+{
+ unsigned int asv_volt;
+
+ if (level >= subsys->num_asv_levels)
+ return volt;
+
+ asv_volt = __exynos_asv_get_item(&subsys->table, level,
+ exynos_asv->group + 1);
+ if (asv_volt == 0 && exynos_asv->group > 1)
+ asv_volt = __exynos_asv_get_item(&subsys->table, level, 1);
+
+ if (volt > subsys->base_volt)
+ asv_volt += subsys->offset_volt_h;
+ else
+ asv_volt += subsys->offset_volt_l;
+
+ return asv_volt;
+}
+
+static void __init exynos5422_asv_release(struct exynos_asv *asv)
+{
+ kfree(asv->arm.table.buf);
+ asv->arm.table.buf = NULL;
+ kfree(asv->kfc.table.buf);
+ asv->kfc.table.buf = NULL;
+}
+
+int __init exynos5422_asv_init(struct exynos_asv *asv)
+{
+ struct device_node *node;
+ unsigned int table_index;
+ int ret;
+
+ exynos_asv = asv;
+
+ asv->is_bin2 = exynos5422_asv_check_bin2();
+ asv->is_special_lot = exynos5422_asv_check_lot_id();
+
+ if (of_machine_is_compatible("hardkernel,odroid-xu3-lite")) {
+ asv->is_bin2 = true;
+ asv->is_special_lot = false;
+ }
+
+ asv->group = exynos5422_asv_get_group(asv);
+ asv->table = exynos5422_asv_get_table();
+
+ exynos5422_asv_offset_voltage_setup(asv);
+
+ node = of_find_compatible_node(NULL, NULL, "samsung,exynos-asv-v1");
+ if (!node)
+ return -ENODEV;
+
+ if (!asv->is_bin2) {
+ if (asv->table == 2 || asv->table == 3)
+ table_index = asv->table;
+ else
+ table_index = 0;
+ } else {
+ table_index = 4;
+ }
+
+ ret = exynos_asv_parse_cpu_tables(asv, node, table_index);
+ of_node_put(node);
+ if (ret < 0)
+ return ret;
+
+ asv->arm.cpu_dt_compat = "arm,cortex-a15";
+ asv->kfc.cpu_dt_compat = "arm,cortex-a7";
+
+ asv->opp_get_voltage = exynos5422_asv_opp_get_voltage;
+ asv->release = exynos5422_asv_release;
+
+ return ret;
+}
diff --git a/drivers/soc/samsung/exynos5422-asv.h b/drivers/soc/samsung/exynos5422-asv.h
new file mode 100644
index 000000000000..f0d9107d6d0a
--- /dev/null
+++ b/drivers/soc/samsung/exynos5422-asv.h
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com/
+ *
+ * Samsung Exynos 5422 SoC Adaptive Supply Voltage support
+ */
+
+#ifndef __EXYNOS5422_ASV_H
+#define __EXYNOS5422_ASV_H
+
+#include <linux/errno.h>
+
+struct exynos_asv;
+
+#ifdef CONFIG_EXYNOS_ASV_ARM
+int exynos5422_asv_init(struct exynos_asv *asv);
+#else
+static inline int exynos5422_asv_init(struct exynos_asv *asv)
+{
+ return -ENOTSUPP;
+}
+#endif
+
+#endif /* __EXYNOS5422_ASV_H */
--
2.17.1

2019-04-04 17:24:09

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 6/8] ARM64: EXYNOS: enable exynos_chipid for ARCH_EXYNOS

From: Pankaj Dubey <[email protected]>

This patch enables exynos_chipid driver for ARCH_EXYNOS
based SoC.

Signed-off-by: Pankaj Dubey <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
---
arch/arm64/Kconfig.platforms | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 70498a033cf5..794c65a4910a 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -67,6 +67,7 @@ config ARCH_BRCMSTB
config ARCH_EXYNOS
bool "ARMv8 based Samsung Exynos SoC family"
select COMMON_CLK_SAMSUNG
+ select EXYNOS_CHIPID
select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
select EXYNOS_PMU
select HAVE_S3C2410_WATCHDOG if WATCHDOG
--
2.17.1

2019-04-04 17:24:09

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 5/8] ARM: EXYNOS: enable exynos_chipid for ARCH_EXYNOS

From: Pankaj Dubey <[email protected]>

As now we have chipid driver to initialize SoC related information
let's include it in build by default.

Signed-off-by: Pankaj Dubey <[email protected]>
Reviewed-by: Krzysztof Kozlowski <[email protected]>
Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
---
arch/arm/mach-exynos/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index b40963cf91c7..e3e63aa5d60a 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -13,6 +13,7 @@ menuconfig ARCH_EXYNOS
select ARM_AMBA
select ARM_GIC
select COMMON_CLK_SAMSUNG
+ select EXYNOS_CHIPID
select EXYNOS_THERMAL
select EXYNOS_PMU
select EXYNOS_SROM
--
2.17.1

2019-04-04 17:24:26

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 7/8] ARM: EXYNOS: Enable exynos-asv driver for ARCH_EXYNOS

Enable exynos-asv driver for Exynos 32-bit SoCs.

Signed-off-by: Sylwester Nawrocki <[email protected]>
---
arch/arm/mach-exynos/Kconfig | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig
index e3e63aa5d60a..fe306a85228c 100644
--- a/arch/arm/mach-exynos/Kconfig
+++ b/arch/arm/mach-exynos/Kconfig
@@ -13,6 +13,7 @@ menuconfig ARCH_EXYNOS
select ARM_AMBA
select ARM_GIC
select COMMON_CLK_SAMSUNG
+ select EXYNOS_ASV
select EXYNOS_CHIPID
select EXYNOS_THERMAL
select EXYNOS_PMU
--
2.17.1

2019-04-04 17:24:39

by Sylwester Nawrocki

[permalink] [raw]
Subject: [PATCH RFC 8/8] ARM: dts: exynos: Add ASV tables for exynos5422/5800

This patch ASV (Adaptive Supply Voltage) table entries for
Exynos5422/5800 SoC.

Signed-off-by: Sylwester Nawrocki <[email protected]>
---
arch/arm/boot/dts/exynos5.dtsi | 2 +-
arch/arm/boot/dts/exynos5800.dtsi | 207 ++++++++++++++++++++++++++++++
2 files changed, 208 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index 67f9b4504a42..22eb951c614c 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -35,7 +35,7 @@
#size-cells = <1>;
ranges;

- chipid@10000000 {
+ chipid: chipid@10000000 {
compatible = "samsung,exynos4210-chipid";
reg = <0x10000000 0x100>;
};
diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
index 57d3b319fd65..5358865f5c0b 100644
--- a/arch/arm/boot/dts/exynos5800.dtsi
+++ b/arch/arm/boot/dts/exynos5800.dtsi
@@ -16,6 +16,213 @@
compatible = "samsung,exynos5800", "samsung,exynos5";
};

+&chipid {
+ asv {
+ compatible = "samsung,exynos-asv-v1";
+ asv-table-0 {
+ /* ARM 0, 1 */
+ samsung,asv-table-size = <20 15>;
+ samsung,asv-table-id = <0x0>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
+ <2000 1312500 1312500 1300000 1287500 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
+ <1900 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1162500 1150000 1137500 1125000 1112500>,
+ <1800 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1112500 1100000 1087500 1075000 1062500>,
+ <1700 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1075000 1062500 1050000 1037500 1025000>,
+ <1600 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1037500 1025000 1012500 1000000 987500>,
+ <1500 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 1000000 987500 975000 962500 950000>,
+ <1400 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 975000 962500 950000 937500 925000>,
+ <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
+ <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
+ <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
+ <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <700 900000>,
+ <600 900000>,
+ <500 900000>,
+ <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+ asv-table-2 {
+ /* ARM 2 */
+ samsung,asv-table-size = <20 15>;
+ samsung,asv-table-id = <0x2>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
+ <2000 1312500 1312500 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
+ <1900 1262500 1250000 1250000 1237500 1212500 1200000 1187500 1175000 1162500 1175000 1162500 1150000 1137500 1125000>,
+ <1800 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1125000 1112500 1100000 1087500 1075000>,
+ <1700 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1087500 1075000 1062500 1050000 1037500>,
+ <1600 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1050000 1037500 1025000 1012500 1000000>,
+ <1500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
+ <1400 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 987500 975000 962500 950000 937500>,
+ <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
+ <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
+ <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
+ <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <700 900000>,
+ <600 900000>,
+ <500 900000>,
+ <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+ asv-table-3 {
+ /* ARM 3 */
+ samsung,asv-table-size = <20 15>;
+ samsung,asv-table-id = <0x3>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
+ <2000 1312500 1312500 1300000 1287500 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
+ <1900 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1175000 1162500 1150000 1137500 1125000>,
+ <1800 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1125000 1112500 1100000 1087500 1075000>,
+ <1700 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1087500 1075000 1062500 1050000 1037500>,
+ <1600 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1050000 1037500 1025000 1012500 1000000>,
+ <1500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
+ <1400 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 987500 975000 962500 950000 937500>,
+ <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
+ <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
+ <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
+ <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <700 900000>,
+ <600 900000>,
+ <500 900000>,
+ <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+
+ asv-table-4 {
+ /* ARM BIN2 */
+ samsung,asv-table-size = <17 15>;
+ samsung,asv-table-id = <0x4>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <1800 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1150000 1137500 1125000 1112500 1100000>,
+ <1700 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1112500 1100000 1087500 1075000 1062500>,
+ <1600 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1075000 1062500 1050000 1037500 1025000>,
+ <1500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1037500 1025000 1012500 1000000 987500>,
+ <1400 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
+ <1300 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 1000000 987500 975000 962500 950000>,
+ <1200 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 975000 962500 950000 937500 925000>,
+ <1100 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 950000 937500 925000 912500 900000>,
+ <1000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 925000 912500 900000 900000 900000>,
+ < 900 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
+ < 800 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 700 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <600 900000>,
+ <500 900000>,
+ <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+
+
+ asv-table-100 {
+ /* KFC 0, 1 */
+ samsung,asv-table-size = <14 15>;
+ samsung,asv-table-id = <0x100>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
+ <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
+ <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
+ <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
+ <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
+ <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
+ < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
+ < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
+ < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
+ < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+
+ asv-table-102 {
+ /* KFC 2 */
+ samsung,asv-table-size = <14 15>;
+ samsung,asv-table-id = <0x102>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
+ <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
+ <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
+ <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
+ <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
+ <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
+ < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
+ < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
+ < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
+ < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+
+ asv-table-103 {
+ /* KFC 3 */
+ samsung,asv-table-size = <14 15>;
+ samsung,asv-table-id = <0x103>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
+ <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
+ <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
+ <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
+ <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
+ <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
+ < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
+ < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
+ < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
+ < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <400 900000>,
+ <300 900000>,
+ <200 900000>;
+ };
+
+ asv-table-104 {
+ /* KFC BIN2 */
+ samsung,asv-table-size = <12 15>;
+ samsung,asv-table-id = <0x104>;
+ samsung,asv-data =
+ /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
+ <1300 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500>,
+ <1200 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500>,
+ <1100 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000>,
+ <1000 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500>,
+ < 900 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000>,
+ < 800 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000>,
+ < 700 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000>,
+ < 600 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 500 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
+ < 400 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
+ /* ASV0...13 */
+ samsung,asv-common-data = <300 900000>,
+ <200 900000>;
+ };
+ };
+};
+
&clock {
compatible = "samsung,exynos5800-clock";
};
--
2.17.1

2019-04-05 06:54:45

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH RFC 1/8] soc: samsung: Add exynos chipid driver support

On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>
> From: Pankaj Dubey <[email protected]>
>
> Exynos SoCs have Chipid, for identification of product IDs and SoC
> revisions. This patch intends to provide initialization code for all
> these functionalities, at the same time it provides some sysfs entries
> for accessing these information to user-space.
>
> This driver uses existing binding for exynos-chipid.
>
> Changes by Bartlomiej:
> - fixed return values on errors
> - removed bogus kfree_const()
> - added missing Exynos4210 EVT0 id
> - converted code to use EXYNOS_MASK define
> - fixed np use after of_node_put()
> - fixed too early use of dev_info()
> - made driver fail for unknown SoC-s
> - added SPDX tag
> - updated Copyrights
>
> Signed-off-by: Pankaj Dubey <[email protected]>
> [m.szyprowski: for suggestion and code snippet of product_id_to_soc_id]
> Signed-off-by: Marek Szyprowski <[email protected]>
> Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>

Toy need to add your SoB here.

> ---
> drivers/soc/samsung/Kconfig | 5 ++
> drivers/soc/samsung/Makefile | 2 +
> drivers/soc/samsung/exynos-chipid.c | 111 ++++++++++++++++++++++++++++
> 3 files changed, 118 insertions(+)
> create mode 100644 drivers/soc/samsung/exynos-chipid.c
>
> diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
> index 2186285fda92..2905f5262197 100644
> --- a/drivers/soc/samsung/Kconfig
> +++ b/drivers/soc/samsung/Kconfig
> @@ -7,6 +7,11 @@ menuconfig SOC_SAMSUNG
>
> if SOC_SAMSUNG
>
> +config EXYNOS_CHIPID
> + bool "Exynos Chipid controller driver" if COMPILE_TEST
> + depends on ARCH_EXYNOS || COMPILE_TEST
> + select SOC_BUS
> +
> config EXYNOS_PMU
> bool "Exynos PMU controller driver" if COMPILE_TEST
> depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
> diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
> index 29f294baac6e..3b6a8797416c 100644
> --- a/drivers/soc/samsung/Makefile
> +++ b/drivers/soc/samsung/Makefile
> @@ -1,4 +1,6 @@
> # SPDX-License-Identifier: GPL-2.0
> +
> +obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
> obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
>
> obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS) += exynos3250-pmu.o exynos4-pmu.o \
> diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
> new file mode 100644
> index 000000000000..5cb018807817
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos-chipid.c
> @@ -0,0 +1,111 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * EXYNOS - CHIP ID support
> + * Author: Pankaj Dubey <[email protected]>
> + * Author: Bartlomiej Zolnierkiewicz <[email protected]>
> + */
> +
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>

I commented Bartlomiej's patch which you included here. I did not
receive any further feedback from him so I do not know whether he
agrees with my comments or not... but if you send the same patch again
without addressing these comments, I feel like ignored.

I stopped on first ignored comment.

Therefore please address be sure that you addressed my comments from
Bartlomiej's patchset. If you do not agree with them, please let me
know. The comments are here:
https://patchwork.kernel.org/project/linux-samsung-soc/list/?series=43565&state=*

Best regards,
Krzysztof

> +#include <linux/slab.h>
> +#include <linux/sys_soc.h>
> +
> +#define EXYNOS_SUBREV_MASK (0xF << 4)
> +#define EXYNOS_MAINREV_MASK (0xF << 0)
> +#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
> +#define EXYNOS_MASK 0xFFFFF000
> +
> +static const struct exynos_soc_id {
> + const char *name;
> + unsigned int id;
> +} soc_ids[] = {
> + { "EXYNOS3250", 0xE3472000 },
> + { "EXYNOS4210", 0x43200000 }, /* EVT0 revision */
> + { "EXYNOS4210", 0x43210000 },
> + { "EXYNOS4212", 0x43220000 },
> + { "EXYNOS4412", 0xE4412000 },
> + { "EXYNOS5250", 0x43520000 },
> + { "EXYNOS5260", 0xE5260000 },
> + { "EXYNOS5410", 0xE5410000 },
> + { "EXYNOS5420", 0xE5420000 },
> + { "EXYNOS5440", 0xE5440000 },
> + { "EXYNOS5800", 0xE5422000 },
> + { "EXYNOS7420", 0xE7420000 },
> + { "EXYNOS5433", 0xE5433000 },
> +};
> +
> +static const char * __init product_id_to_soc_id(unsigned int product_id)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(soc_ids); i++)
> + if ((product_id & EXYNOS_MASK) == soc_ids[i].id)
> + return soc_ids[i].name;
> + return NULL;
> +}
> +
> +int __init exynos_chipid_early_init(void)
> +{
> + struct soc_device_attribute *soc_dev_attr;
> + void __iomem *exynos_chipid_base;
> + struct soc_device *soc_dev;
> + struct device_node *root;
> + struct device_node *np;
> + u32 product_id;
> + u32 revision;
> +
> + /* look up for chipid node */
> + np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
> + if (!np)
> + return -ENODEV;
> +
> + exynos_chipid_base = of_iomap(np, 0);
> + of_node_put(np);
> +
> + if (!exynos_chipid_base) {
> + pr_err("Failed to map SoC chipid\n");
> + return -ENXIO;
> + }
> +
> + product_id = readl_relaxed(exynos_chipid_base);
> + revision = product_id & EXYNOS_REV_MASK;
> + iounmap(exynos_chipid_base);
> +
> + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
> + if (!soc_dev_attr)
> + return -ENOMEM;
> +
> + soc_dev_attr->family = "Samsung Exynos";
> +
> + root = of_find_node_by_path("/");
> + of_property_read_string(root, "model", &soc_dev_attr->machine);
> + of_node_put(root);
> +
> + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x", revision);
> + soc_dev_attr->soc_id = product_id_to_soc_id(product_id);
> + if (!soc_dev_attr->soc_id) {
> + pr_err("Unknown SoC\n");
> + return -ENODEV;
> + }
> +
> + /* please note that the actual registration will be deferred */
> + soc_dev = soc_device_register(soc_dev_attr);
> + if (IS_ERR(soc_dev)) {
> + kfree(soc_dev_attr->revision);
> + kfree(soc_dev_attr);
> + return PTR_ERR(soc_dev);
> + }
> +
> + /* it is too early to use dev_info() here (soc_dev is NULL) */
> + pr_info("soc soc0: Exynos: CPU[%s] PRO_ID[0x%x] REV[0x%x] Detected\n",
> + soc_dev_attr->soc_id, product_id, revision);
> +
> + return 0;
> +}
> +early_initcall(exynos_chipid_early_init);
> --
> 2.17.1
>

2019-04-05 08:50:53

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH RFC 1/8] soc: samsung: Add exynos chipid driver support

On 4/5/19 08:53, Krzysztof Kozlowski wrote:
> On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>> From: Pankaj Dubey <[email protected]>
>>
>> Exynos SoCs have Chipid, for identification of product IDs and SoC
>> revisions. This patch intends to provide initialization code for all
>> these functionalities, at the same time it provides some sysfs entries
>> for accessing these information to user-space.

>> Signed-off-by: Pankaj Dubey <[email protected]>
>> [m.szyprowski: for suggestion and code snippet of product_id_to_soc_id]
>> Signed-off-by: Marek Szyprowski <[email protected]>
>> Signed-off-by: Bartlomiej Zolnierkiewicz <[email protected]>
>
> Toy need to add your SoB here.

Will correct that in next iteration.

>> diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
>> new file mode 100644
>> index 000000000000..5cb018807817
>> --- /dev/null
>> +++ b/drivers/soc/samsung/exynos-chipid.c
>> @@ -0,0 +1,111 @@

>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +#include <linux/platform_device.h>
>
> I commented Bartlomiej's patch which you included here. I did not
> receive any further feedback from him so I do not know whether he
> agrees with my comments or not... but if you send the same patch again
> without addressing these comments, I feel like ignored.
>
> I stopped on first ignored comment.
>
> Therefore please address be sure that you addressed my comments from
> Bartlomiej's patchset. If you do not agree with them, please let me
> know. The comments are here:
> https://patchwork.kernel.org/project/linux-samsung-soc/list/?series=43565&state=*

I will drop that unneeded header inclusion in next iteration. It was
just my oversight, I somehow missed your previous comments. And of
course your reviews are appreciated.

--
Regards,
Sylwester

2019-04-05 09:24:59

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH RFC 2/8] soc: samsung: Exynos chipid driver update

On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>
> This patch adds definition of selected CHIP ID register offsets
> and register bit field definitions for Exynos5422 SoC.
>
> exynos_chipid_read() helper function is added to allow reading
> the CHIP ID block registers.
>
> Signed-off-by: Sylwester Nawrocki <[email protected]>
> ---
> drivers/soc/samsung/exynos-chipid.c | 16 +++++-----
> drivers/soc/samsung/exynos-chipid.h | 48 +++++++++++++++++++++++++++++
> 2 files changed, 57 insertions(+), 7 deletions(-)
> create mode 100644 drivers/soc/samsung/exynos-chipid.h
>
> diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
> index 5cb018807817..4920f0ef2c55 100644
> --- a/drivers/soc/samsung/exynos-chipid.c
> +++ b/drivers/soc/samsung/exynos-chipid.c
> @@ -16,10 +16,7 @@
> #include <linux/slab.h>
> #include <linux/sys_soc.h>
>
> -#define EXYNOS_SUBREV_MASK (0xF << 4)
> -#define EXYNOS_MAINREV_MASK (0xF << 0)
> -#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
> -#define EXYNOS_MASK 0xFFFFF000

Create hex-addresses in first commit in lower case.

> +#include "exynos-chipid.h"
>
> static const struct exynos_soc_id {
> const char *name;
> @@ -40,6 +37,13 @@ static const struct exynos_soc_id {
> { "EXYNOS5433", 0xE5433000 },
> };
>
> +static void __iomem *exynos_chipid_base;

No, this was removed in Pankaj's version v6 -> v7 and I do not want it
to be file-scope. Having it file-scope is error prone and prevents
having multiple instances (I do not expect having more than one but
still code should be rather nicely generic).

> +
> +unsigned int exynos_chipid_read(unsigned int offset)
> +{
> + return readl_relaxed(exynos_chipid_base + offset);
> +}
> +
> static const char * __init product_id_to_soc_id(unsigned int product_id)
> {
> int i;
> @@ -53,7 +57,6 @@ static const char * __init product_id_to_soc_id(unsigned int product_id)
> int __init exynos_chipid_early_init(void)
> {
> struct soc_device_attribute *soc_dev_attr;
> - void __iomem *exynos_chipid_base;
> struct soc_device *soc_dev;
> struct device_node *root;
> struct device_node *np;
> @@ -73,9 +76,8 @@ int __init exynos_chipid_early_init(void)
> return -ENXIO;
> }
>
> - product_id = readl_relaxed(exynos_chipid_base);
> + product_id = exynos_chipid_read(EXYNOS_CHIPID_REG_PRO_ID);
> revision = product_id & EXYNOS_REV_MASK;
> - iounmap(exynos_chipid_base);
>
> soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
> if (!soc_dev_attr)
> diff --git a/drivers/soc/samsung/exynos-chipid.h b/drivers/soc/samsung/exynos-chipid.h
> new file mode 100644
> index 000000000000..826a12c25fa2
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos-chipid.h
> @@ -0,0 +1,48 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * EXYNOS - CHIP ID support
> + */
> +
> +#define EXYNOS_CHIPID_REG_PRO_ID 0x00
> + #define EXYNOS_SUBREV_MASK (0xf << 4)
> + #define EXYNOS_MAINREV_MASK (0xf << 0)
> + #define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \
> + EXYNOS_MAINREV_MASK)
> + #define EXYNOS_MASK 0xfffff000
> +
> +#define EXYNOS_CHIPID_REG_PKG_ID 0x04

Can you comment that these are fields from this register?
The same in second one.

Best regards,
Krzysztof

> + #define EXYNOS5422_IDS_OFFSET 24
> + #define EXYNOS5422_IDS_MASK 0xff
> + #define EXYNOS5422_USESG_OFFSET 3
> + #define EXYNOS5422_USESG_MASK 0x01
> + #define EXYNOS5422_SG_OFFSET 0
> + #define EXYNOS5422_SG_MASK 0x07
> + #define EXYNOS5422_TABLE_OFFSET 8
> + #define EXYNOS5422_TABLE_MASK 0x03
> + #define EXYNOS5422_SG_A_OFFSET 17
> + #define EXYNOS5422_SG_A_MASK 0x0f
> + #define EXYNOS5422_SG_B_OFFSET 21
> + #define EXYNOS5422_SG_B_MASK 0x03
> + #define EXYNOS5422_SG_BSIGN_OFFSET 23
> + #define EXYNOS5422_SG_BSIGN_MASK 0x01
> + #define EXYNOS5422_BIN2_OFFSET 12
> + #define EXYNOS5422_BIN2_MASK 0x01
> +
> +#define EXYNOS_CHIPID_REG_LOT_ID 0x14
> +
> +#define EXYNOS_CHIPID_AUX_INFO 0x1c
> + #define EXYNOS5422_TMCB_OFFSET 0
> + #define EXYNOS5422_TMCB_MASK 0x7f
> + #define EXYNOS5422_ARM_UP_OFFSET 8
> + #define EXYNOS5422_ARM_UP_MASK 0x03
> + #define EXYNOS5422_ARM_DN_OFFSET 10
> + #define EXYNOS5422_ARM_DN_MASK 0x03
> + #define EXYNOS5422_KFC_UP_OFFSET 12
> + #define EXYNOS5422_KFC_UP_MASK 0x03
> + #define EXYNOS5422_KFC_DN_OFFSET 14
> + #define EXYNOS5422_KFC_DN_MASK 0x03
> +
> +unsigned int exynos_chipid_read(unsigned int offset);
> --
> 2.17.1
>

2019-04-05 10:05:25

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH RFC 2/8] soc: samsung: Exynos chipid driver update

On 4/5/19 11:22, Krzysztof Kozlowski wrote:
> On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>>
>> This patch adds definition of selected CHIP ID register offsets
>> and register bit field definitions for Exynos5422 SoC.
>>
>> exynos_chipid_read() helper function is added to allow reading
>> the CHIP ID block registers.
>>
>> Signed-off-by: Sylwester Nawrocki <[email protected]>
>> ---
>> drivers/soc/samsung/exynos-chipid.c | 16 +++++-----
>> drivers/soc/samsung/exynos-chipid.h | 48 +++++++++++++++++++++++++++++
>> 2 files changed, 57 insertions(+), 7 deletions(-)
>> create mode 100644 drivers/soc/samsung/exynos-chipid.h
>>
>> diff --git a/drivers/soc/samsung/exynos-chipid.c b/drivers/soc/samsung/exynos-chipid.c
>> index 5cb018807817..4920f0ef2c55 100644
>> --- a/drivers/soc/samsung/exynos-chipid.c
>> +++ b/drivers/soc/samsung/exynos-chipid.c
>> @@ -16,10 +16,7 @@

>> -#define EXYNOS_SUBREV_MASK (0xF << 4)
>> -#define EXYNOS_MAINREV_MASK (0xF << 0)
>> -#define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | EXYNOS_MAINREV_MASK)
>> -#define EXYNOS_MASK 0xFFFFF000
>
> Create hex-addresses in first commit in lower case.

>> +static void __iomem *exynos_chipid_base;
>
> No, this was removed in Pankaj's version v6 -> v7 and I do not want it
> to be file-scope. Having it file-scope is error prone and prevents
> having multiple instances (I do not expect having more than one but
> still code should be rather nicely generic).

I'm going to switch to using regmap so that will not be needed any
more, together with exynos_chipid_read() helper. Then the header
file would be moved to include/linux/soc/samsung.

>> +unsigned int exynos_chipid_read(unsigned int offset)
>> +{
>> + return readl_relaxed(exynos_chipid_base + offset);
>> +}

>> diff --git a/drivers/soc/samsung/exynos-chipid.h b/drivers/soc/samsung/exynos-chipid.h
>> new file mode 100644
>> index 000000000000..826a12c25fa2
>> --- /dev/null
>> +++ b/drivers/soc/samsung/exynos-chipid.h
>> @@ -0,0 +1,48 @@

>> +#define EXYNOS_CHIPID_REG_PRO_ID 0x00
>> + #define EXYNOS_SUBREV_MASK (0xf << 4)
>> + #define EXYNOS_MAINREV_MASK (0xf << 0)
>> + #define EXYNOS_REV_MASK (EXYNOS_SUBREV_MASK | \
>> + EXYNOS_MAINREV_MASK)
>> + #define EXYNOS_MASK 0xfffff000
>> +
>> +#define EXYNOS_CHIPID_REG_PKG_ID 0x04
>
> Can you comment that these are fields from this register?
> The same in second one.

OK, I will add some comment here.

>> + #define EXYNOS5422_IDS_OFFSET 24
>> + #define EXYNOS5422_IDS_MASK 0xff
--
Regards,
Sylwester

2019-04-05 10:25:56

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH RFC 4/8] soc: samsung: Add Exynos Adaptive Supply Voltage driver

Hi Sylwester,

Nice work, thank you!

I have a lot of minor nits all around and few more architecture-like comments.

I think this should be a driver. You initialize it quite late and it
is required by other drivers (cpufreq, devfreq), not by core.

I would also prefer it to be slightly more generic. I mean, now you
get the tables from "samsung,exynos-asv-v1" node and then, depending
on many different compatibles, you do this or that. If it is
samsung,exynos5800, you call 542x code. If it is hardkernel, you
assume it is bin2. This will be not easily portable to other Exynos
chips and other boards (e.g. you need to update the driver for new
board which is forced to be in bin2).

Instead all this information should come from chipid and/or DT. I
could imagine that the device binds to ASV node and parses its
properties. Optionally it could bind to chipid... but then you would
have two devices on same node. Then depending on the of_device_id
match, you have all necessary static configuration data (the same as
PMU driver or all other typical drivers). Dynamic data you read from
chip id.

There are some comments below but I guess the code will change a lot
so there is no point to do through code review.

On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>
> The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
> operating points of devices in order to better match actual capabilities
> of the hardware and optimize power consumption.
>
> This patch adds common code for parsing the ASV tables from devicetree
> and updating CPU OPPs.
>
> Also support for Exynos5422/5800 SoC is added, the Exynos5422 specific part
> of the patch is partially based on code from
> https://github.com/hardkernel/linux repository, branch odroidxu4-4.14.y,
> files: arch/arm/mach-exynos/exynos5422-asv.[ch].
>
> Tested on Odroid XU3, XU4, XU3 Lite.
>
> Signed-off-by: Sylwester Nawrocki <[email protected]>
> ---
> drivers/soc/samsung/Kconfig | 11 ++
> drivers/soc/samsung/Makefile | 3 +
> drivers/soc/samsung/exynos-asv.c | 279 +++++++++++++++++++++++++++
> drivers/soc/samsung/exynos-asv.h | 114 +++++++++++
> drivers/soc/samsung/exynos5422-asv.c | 209 ++++++++++++++++++++
> drivers/soc/samsung/exynos5422-asv.h | 25 +++
> 6 files changed, 641 insertions(+)
> create mode 100644 drivers/soc/samsung/exynos-asv.c
> create mode 100644 drivers/soc/samsung/exynos-asv.h
> create mode 100644 drivers/soc/samsung/exynos5422-asv.c
> create mode 100644 drivers/soc/samsung/exynos5422-asv.h
>
> diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
> index 2905f5262197..4d121984f71a 100644
> --- a/drivers/soc/samsung/Kconfig
> +++ b/drivers/soc/samsung/Kconfig
> @@ -7,6 +7,17 @@ menuconfig SOC_SAMSUNG
>
> if SOC_SAMSUNG
>
> +config EXYNOS_ASV
> + bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST
> + depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)

Why it cannot be compile tested outside of ARM? The PMU driver has
this constraint because of asm/cputype.h but you probably do not need
it.

> + depends on EXYNOS_CHIPID
> + select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS
> +
> +# There is no need to enable these drivers for ARMv8
> +config EXYNOS_ASV_ARM
> + bool "Exynos ASV ARMv7-specific driver extensions" if COMPILE_TEST
> + depends on EXYNOS_ASV
> +
> config EXYNOS_CHIPID
> bool "Exynos Chipid controller driver" if COMPILE_TEST
> depends on ARCH_EXYNOS || COMPILE_TEST
> diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
> index 3b6a8797416c..edd1d6ea064d 100644
> --- a/drivers/soc/samsung/Makefile
> +++ b/drivers/soc/samsung/Makefile
> @@ -1,5 +1,8 @@
> # SPDX-License-Identifier: GPL-2.0
>
> +obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o
> +obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o
> +
> obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
> obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
>
> diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
> new file mode 100644
> index 000000000000..60532c7eb3aa
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos-asv.c
> @@ -0,0 +1,279 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.

Since it is first publish date, copyright should be only 2019....
unless this was copied from hardkernel repo but then original
copyright should be included as well.

> + * http://www.samsung.com/
> + * Author: Sylwester Nawrocki <[email protected]>
> + *
> + * Samsung Exynos SoC Adaptive Supply Voltage support
> + */
> +
> +#include <linux/cpu.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/pm_opp.h>
> +#include <linux/slab.h>
> +
> +#include "exynos-asv.h"
> +#include "exynos5422-asv.h"
> +#include "exynos5433-asv.h"
> +
> +#ifndef MHZ

There is no existing definition, so just #define. It will also easily
be noticed by preprocessor if someone adds such define later.

> +#define MHZ 1000000U
> +#endif
> +
> +static struct exynos_asv *exynos_asv;

Please avoid it. This should be a driver which registers it's state as drvdata.

> +
> +int exynos_asv_parse_of_table(struct device_node *node,

A nit: node->np because it is more popular. And shorter.

> + struct exynos_asv_table *table,
> + int index)
> +{
> + u32 table_size, table_id = 0;
> + unsigned int len1, len2 = 0;

Please move the initialized variables to separate lines (first probably).

> + unsigned int num_cols, num_rows;
> + u32 tmp[20];
> + u32 *buf;
> + int ret;
> +
> + ret = of_property_read_u32(node, "samsung,asv-table-id",
> + &table_id);
> + if (ret < 0) {
> + pr_err("ASV: Missing table id in %pOF\n", node);
> + return ret;
> + }
> + table->id = table_id;
> +
> + if (index >= 0 && asv_table_to_index(table_id) != index)
> + return -EBADR;
> +
> + ret = of_property_read_u32_array(node, "samsung,asv-table-size",
> + tmp, 2);
> + if (ret < 0)
> + return ret;
> +
> + num_rows = tmp[0];
> + num_cols = tmp[1];
> + if (num_rows > EXYNOS_ASV_MAX_LEVELS ||
> + num_cols > (EXYNOS_ASV_MAX_GROUPS + 1)) {
> + pr_err("ASV: Unsupported ASV table size (%d x %d)\n",
> + num_rows, num_cols);
> + return -EINVAL;
> + }
> +
> + table_size = num_rows * num_cols;
> + buf = kcalloc(table_size, sizeof(u32), GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + ret = of_property_read_variable_u32_array(node, "samsung,asv-data",
> + buf, 0, table_size);
> + if (ret < 0)
> + goto err_free_buf;
> +
> + len1 = ret;
> +
> + if (ret < table_size) {
> + u32 *dst, *src;
> + ret = of_property_read_variable_u32_array(node,
> + "samsung,asv-common-data",
> + (u32 *)tmp, 0,
> + ARRAY_SIZE(tmp));
> + if (ret < 0) {
> + pr_err("ASV: Not enough data for table #%x (%d x %d)\n",
> + table_id, num_rows, num_cols);
> + goto err_free_buf;
> + }
> + len2 = ret;
> +
> + if (len1 + ((len2 / 2) * num_cols) > table_size) {
> + pr_err("ASV: Incorrect table %#x definition\n",
> + table_id);
> + ret = -EINVAL;
> + goto err_free_buf;
> + }
> + /*
> + * Copy data common to all ASV levels to first and second column
> + * in the main buffer. We don't replicate data to further
> + * columns, instead they are left initialized to 0 (invalid,
> + * unused frequency value). We assume that users of the table
> + * will refer to voltage data in column 1 if 0 is encountered
> + * in any further column (2, 3,...).
> + */
> + dst = buf + len1;
> + src = tmp;
> +
> + while (len2 >= 2) {
> + memcpy(dst, src, 2 * sizeof(u32));
> + dst += num_cols;
> + src += 2;
> + len2 -= 2;
> + }
> + }
> +
> + table->num_cols = num_cols;
> + table->num_rows = num_rows;
> + table->buf = buf;
> + return 0;
> +
> +err_free_buf:
> + kfree(buf);
> + return ret;
> +}
> +
> +int exynos_asv_parse_cpu_tables(struct exynos_asv *asv, struct device_node *np,
> + int table_index)
> +{
> + struct exynos_asv_subsys *subsys;
> + struct exynos_asv_table table;
> + struct device_node *child;
> + int ret;
> +
> + for_each_child_of_node(np, child) {
> + ret = exynos_asv_parse_of_table(child, &table, table_index);
> + if (ret < 0) {
> + if (ret == -EBADR)
> + continue;
> + of_node_put(child);
> + return ret;
> + }
> +
> + pr_debug("%s: Matching table: id: %#x at %pOF\n",
> + __func__, table.id, child);
> +
> + switch(asv_table_to_subsys_id(table.id)) {
> + case EXYNOS_ASV_SUBSYS_ID_ARM:
> + subsys = &asv->arm;
> + break;
> + case EXYNOS_ASV_SUBSYS_ID_KFC:
> + subsys = &asv->kfc;
> + break;
> + default:
> + of_node_put(child);
> + return -EINVAL;
> + }
> +
> + subsys->num_asv_levels = table.num_rows;
> + subsys->num_asv_groups = table.num_cols - 1;
> + subsys->table = table;
> + subsys->id = asv_table_to_subsys_id(table.id);
> + }
> +
> + return 0;
> +}
> +
> +static int exynos_asv_update_cpu_opps(struct device *cpu)
> +{
> + struct exynos_asv_subsys *subsys = NULL;
> + struct dev_pm_opp *opp;
> + unsigned int opp_freq;
> + int i;
> +
> + if (of_device_is_compatible(cpu->of_node,
> + exynos_asv->arm.cpu_dt_compat))
> + subsys = &exynos_asv->arm;
> + else if (of_device_is_compatible(cpu->of_node,
> + exynos_asv->kfc.cpu_dt_compat))
> + subsys = &exynos_asv->kfc;
> +
> + if (!subsys)
> + return -EINVAL;
> +
> + for (i = 0; i < subsys->num_asv_levels; i++) {
> + unsigned int new_voltage;
> + unsigned int voltage;
> + int timeout = 1000;
> + int err;
> +
> + opp_freq = exynos_asv_opp_get_frequency(subsys, i);
> +
> + opp = dev_pm_opp_find_freq_exact(cpu, opp_freq * MHZ, true);
> + if (IS_ERR(opp)) {
> + pr_info("%s cpu%d opp%d, freq: %u missing\n",
> + __func__, cpu->id, i, opp_freq);
> +
> + continue;
> + }
> +
> + voltage = dev_pm_opp_get_voltage(opp);
> + new_voltage = exynos_asv->opp_get_voltage(subsys, i, voltage);
> + dev_pm_opp_put(opp);
> +
> + opp_freq *= MHZ;
> + dev_pm_opp_remove(cpu, opp_freq);
> +
> + while (--timeout) {
> + opp = dev_pm_opp_find_freq_exact(cpu, opp_freq, true);
> + if (IS_ERR(opp))
> + break;
> + dev_pm_opp_put(opp);
> + msleep(1);
> + }
> +
> + err = dev_pm_opp_add(cpu, opp_freq, new_voltage);
> + if (err < 0)
> + pr_err("%s: Failed to add OPP %u Hz/%u uV for cpu%d\n",
> + __func__, opp_freq, new_voltage, cpu->id);
> + }
> +
> + return 0;
> +}
> +
> +static int exynos_asv_update_opps(void)
> +{
> + struct opp_table *last_opp_table = NULL;
> + struct device *cpu;
> + int ret, cpuid;
> +
> + for_each_possible_cpu(cpuid) {
> + struct opp_table *opp_table;
> +
> + cpu = get_cpu_device(cpuid);
> + if (!cpu)
> + continue;
> +
> + opp_table = dev_pm_opp_get_opp_table(cpu);
> + if (IS_ERR(opp_table))
> + continue;
> +
> + if (!last_opp_table || opp_table != last_opp_table) {
> + last_opp_table = opp_table;
> +
> + ret = exynos_asv_update_cpu_opps(cpu);
> + if (ret < 0)
> + pr_err("%s: Couldn't udate OPPs for cpu%d\n",
> + __func__, cpuid);
> + }
> +
> + dev_pm_opp_put_opp_table(opp_table);
> + }
> +
> + return 0;
> +}
> +
> +static int __init exynos_asv_init(void)
> +{
> + int ret;
> +
> + exynos_asv = kcalloc(1, sizeof(struct exynos_asv), GFP_KERNEL);

sizeof(*exynos_asv)

> + if (!exynos_asv)
> + return -ENOMEM;
> +
> + if (of_machine_is_compatible("samsung,exynos5800") ||
> + of_machine_is_compatible("samsung,exynos5420"))
> + ret = exynos5422_asv_init(exynos_asv);

No, as I mentioned at beginning, bind to specific node and
differentiate behavior based on of_device_id.

> + else
> + return 0;
> +
> + if (ret < 0)
> + return ret;
> +
> + ret = exynos_asv_update_opps();
> +
> + if (exynos_asv->release)
> + exynos_asv->release(exynos_asv);
> +
> + return ret;
> +}
> +late_initcall(exynos_asv_init)
> diff --git a/drivers/soc/samsung/exynos-asv.h b/drivers/soc/samsung/exynos-asv.h
> new file mode 100644
> index 000000000000..3444b361e5e3
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos-asv.h
> @@ -0,0 +1,114 @@
> +// SPDX-License-Identifier: GPL-2.0

In headers this goes with /* */

> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.

Date.

> + * http://www.samsung.com/
> + * Author: Sylwester Nawrocki <[email protected]>
> + *
> + * Samsung Exynos SoC Adaptive Supply Voltage support
> + */
> +#ifndef __EXYNOS_ASV_H
> +#define __EXYNOS_ASV_H
> +
> +#define EXYNOS_ASV_MAX_GROUPS 16
> +#define EXYNOS_ASV_MAX_LEVELS 24
> +
> +#define EXYNOS_ASV_TABLE_INDEX_MASK (0xff)
> +#define EXYNOS_ASV_SUBSYS_ID_MASK (0xff << 8)
> +
> +#define asv_table_to_subsys_id(_id) ((_id >> 8) & 0xff)
> +#define asv_table_to_index(_id) ((_id) & 0xff)
> +
> +#define EXYNOS_ASV_SUBSYS_ID_ARM 0x0
> +#define EXYNOS_ASV_SUBSYS_ID_EGL EXYNOS_ASV_SUBSYS_ID_ARM
> +#define EXYNOS_ASV_SUBSYS_ID_KFC 0x1
> +#define EXYNOS_ASV_SUBSYS_ID_INT 0x2
> +#define EXYNOS_ASV_SUBSYS_ID_MIF 0x3
> +#define EXYNOS_ASV_SUBSYS_ID_G3D 0x4
> +#define EXYNOS_ASV_SUBSYS_ID_CAM 0x5
> +#define EXYNOS_ASV_SUBSYS_ID_MAX 0x6
> +
> +struct device_node;
> +
> +/* HPM, IDS values to select target group */
> +struct asv_limit_entry {
> + unsigned int hpm;
> + unsigned int ids;
> +};
> +
> +struct exynos_asv_table {
> + unsigned int num_rows;
> + unsigned int num_cols;
> + unsigned int id;
> + u32 *buf;
> +};
> +
> +struct exynos_asv_subsys {
> + int id;
> + char *cpu_dt_compat;
> +
> + unsigned int base_volt;
> + unsigned int num_asv_levels;
> + unsigned int num_asv_groups;
> + unsigned int offset_volt_h;
> + unsigned int offset_volt_l;
> + struct exynos_asv_table table;
> +};
> +
> +struct exynos_asv {
> + struct device_node *chipid_node;
> + struct exynos_asv_subsys arm;
> + struct exynos_asv_subsys kfc;
> +
> + int (*opp_get_voltage)(struct exynos_asv_subsys *subs, int level,
> + unsigned int voltage);
> + void (*release)(struct exynos_asv *asv);
> +
> + unsigned int group;
> + unsigned int table;
> +
> + /* TODO: Move member fields below to SoC type specific data structure */
> + unsigned int is_bin2;
> + unsigned int is_special_lot;
> +};
> +
> +static inline u32 __exynos_asv_get_item(struct exynos_asv_table *table,
> + unsigned int row, unsigned int col)
> +{
> + return table->buf[row * (table->num_cols) + col];
> +}
> +
> +static inline u32 exynos_asv_opp_get_frequency(struct exynos_asv_subsys *subsys,
> + unsigned int index)
> +{
> + return __exynos_asv_get_item(&subsys->table, index, 0);
> +}

Empty line needed.

> +/**
> + * exynos_asv_parse_of_table - Parse ASV table from devicetree
> + *
> + * @node: DT node containing the table
> + * @table: The parsed table data
> + * @index: Used to select table with specific index to parse, if >= 0.
> + * This argument is ignored if the value is less than 0.
> + *
> + * Returns: 0 on success, or negative value on failure. EBADR is returned
> + * when @index is >= 0 but the index value of the parsed table ID is different
> + * than @index.
> + */
> +int exynos_asv_parse_of_table(struct device_node *node,
> + struct exynos_asv_table *table,
> + int index);
> +
> +/**
> + * exynos_asv_parse_cpu_tables - Parse ARM and KFC ASV tables from DT
> + *
> + * @asv: data structure to store the parsed data to
> + * @node: DT node containing the tables
> + * @index: Used to select table with specific index to parse, if >= 0.
> + * This argument is ignored if the value is less than 0.
> + *
> + * Returns: 0 on success, or negative value on failure.
> + */
> +int exynos_asv_parse_cpu_tables(struct exynos_asv *asv, struct device_node *np,
> + int table_index);
> +
> +#endif /* __EXYNOS_ASV_H */
> diff --git a/drivers/soc/samsung/exynos5422-asv.c b/drivers/soc/samsung/exynos5422-asv.c
> new file mode 100644
> index 000000000000..f0b7bdd873a9
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos5422-asv.c
> @@ -0,0 +1,209 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.

The same - copyright date.

> + * http://www.samsung.com/
> + *
> + * Samsung Exynos 5422 SoC Adaptive Supply Voltage support
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include "exynos-asv.h"
> +#include "exynos-chipid.h"
> +
> +#define EXYNOS5422_NUM_ASV_GROUPS 14
> +
> +static struct exynos_asv *exynos_asv;
> +
> +static int exynos5422_asv_get_table(void)
> +{
> + unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
> +
> + return (reg >> EXYNOS5422_TABLE_OFFSET) & EXYNOS5422_TABLE_MASK;
> +}
> +
> +static int exynos5422_asv_check_bin2(void)
> +{
> + unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
> +
> + return (reg >> EXYNOS5422_BIN2_OFFSET) & EXYNOS5422_BIN2_MASK;
> +}
> +
> +static bool exynos5422_asv_check_lot_id(void)
> +{
> + unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
> +
> + return ((reg >> EXYNOS5422_USESG_OFFSET) & EXYNOS5422_USESG_MASK);
> +}
> +
> +static const struct asv_limit_entry __asv_limits[EXYNOS5422_NUM_ASV_GROUPS] = {
> + { 13, 55 },
> + { 21, 65 },
> + { 25, 69 },
> + { 30, 72 },
> + { 36, 74 },
> + { 43, 76 },
> + { 51, 78 },
> + { 65, 80 },
> + { 81, 82 },
> + { 98, 84 },
> + { 119, 87 },
> + { 135, 89 },
> + { 150, 92 },
> + { 999, 999 },
> +};
> +
> +static int exynos5422_asv_get_group(struct exynos_asv *asv)
> +{
> + unsigned int pkgid_reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
> + unsigned int auxi_reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
> + int hpm, ids, i;
> +
> + if (asv->is_special_lot) {
> + u32 sga = (pkgid_reg >> EXYNOS5422_SG_A_OFFSET) &
> + EXYNOS5422_SG_A_MASK;
> +
> + u32 sgb = (pkgid_reg >> EXYNOS5422_SG_B_OFFSET) &
> + EXYNOS5422_SG_B_MASK;
> +
> + if ((pkgid_reg >> EXYNOS5422_SG_BSIGN_OFFSET) &
> + EXYNOS5422_SG_BSIGN_MASK)
> + return sga + sgb;
> + else
> + return sga - sgb;
> + }
> +
> + hpm = (auxi_reg >> EXYNOS5422_TMCB_OFFSET) & EXYNOS5422_TMCB_MASK;
> + ids = (pkgid_reg >> EXYNOS5422_IDS_OFFSET) & EXYNOS5422_IDS_MASK;
> +
> + for (i = 0; i < EXYNOS5422_NUM_ASV_GROUPS; i++) {
> + if (ids <= __asv_limits[i].ids)
> + break;
> + if (hpm <= __asv_limits[i].hpm)
> + break;
> + }
> + if (i < EXYNOS5422_NUM_ASV_GROUPS)
> + return i;
> +
> + return 0;
> +}
> +
> +static int __asv_offset_voltage(unsigned int index)
> +{
> + static const unsigned int offset_table[] = { 12500, 50000, 25000 };
> +
> + if (index == 0 || index > 3)
> + return 0;
> +
> + return offset_table[index - 1];
> +}
> +
> +static void exynos5422_asv_offset_voltage_setup(struct exynos_asv *asv)
> +{
> + struct exynos_asv_subsys *subsys;
> + unsigned int reg, value;
> +
> + reg = exynos_chipid_read(EXYNOS_CHIPID_AUX_INFO);
> +
> + /* ARM offset voltage setup */
> + subsys = &asv->arm;
> +
> + subsys->base_volt = 1000000;
> +
> + value = (reg >> EXYNOS5422_ARM_UP_OFFSET) & EXYNOS5422_ARM_UP_MASK;
> + subsys->offset_volt_h = __asv_offset_voltage(value);
> +
> + value = (reg >> EXYNOS5422_ARM_DN_OFFSET) & EXYNOS5422_ARM_DN_MASK;
> + subsys->offset_volt_l = __asv_offset_voltage(value);
> +
> + /* KFC offset voltage setup */
> + subsys = &asv->kfc;
> +
> + subsys->base_volt = 1000000;
> +
> + value = (reg >> EXYNOS5422_KFC_UP_OFFSET) & EXYNOS5422_KFC_UP_MASK;
> + subsys->offset_volt_h = __asv_offset_voltage(value);
> +
> + value = (reg >> EXYNOS5422_KFC_DN_OFFSET) & EXYNOS5422_KFC_DN_MASK;
> + subsys->offset_volt_l = __asv_offset_voltage(value);
> +}
> +
> +static int exynos5422_asv_opp_get_voltage(struct exynos_asv_subsys *subsys,
> + int level, unsigned int volt)
> +{
> + unsigned int asv_volt;
> +
> + if (level >= subsys->num_asv_levels)
> + return volt;
> +
> + asv_volt = __exynos_asv_get_item(&subsys->table, level,
> + exynos_asv->group + 1);
> + if (asv_volt == 0 && exynos_asv->group > 1)
> + asv_volt = __exynos_asv_get_item(&subsys->table, level, 1);
> +
> + if (volt > subsys->base_volt)
> + asv_volt += subsys->offset_volt_h;
> + else
> + asv_volt += subsys->offset_volt_l;
> +
> + return asv_volt;
> +}
> +
> +static void __init exynos5422_asv_release(struct exynos_asv *asv)
> +{
> + kfree(asv->arm.table.buf);
> + asv->arm.table.buf = NULL;
> + kfree(asv->kfc.table.buf);
> + asv->kfc.table.buf = NULL;
> +}
> +
> +int __init exynos5422_asv_init(struct exynos_asv *asv)
> +{
> + struct device_node *node;
> + unsigned int table_index;
> + int ret;
> +
> + exynos_asv = asv;
> +
> + asv->is_bin2 = exynos5422_asv_check_bin2();
> + asv->is_special_lot = exynos5422_asv_check_lot_id();
> +
> + if (of_machine_is_compatible("hardkernel,odroid-xu3-lite")) {
> + asv->is_bin2 = true;
> + asv->is_special_lot = false;
> + }
> +
> + asv->group = exynos5422_asv_get_group(asv);
> + asv->table = exynos5422_asv_get_table();
> +
> + exynos5422_asv_offset_voltage_setup(asv);
> +
> + node = of_find_compatible_node(NULL, NULL, "samsung,exynos-asv-v1");
> + if (!node)
> + return -ENODEV;
> +
> + if (!asv->is_bin2) {
> + if (asv->table == 2 || asv->table == 3)
> + table_index = asv->table;
> + else
> + table_index = 0;
> + } else {
> + table_index = 4;
> + }
> +
> + ret = exynos_asv_parse_cpu_tables(asv, node, table_index);
> + of_node_put(node);
> + if (ret < 0)
> + return ret;
> +
> + asv->arm.cpu_dt_compat = "arm,cortex-a15";
> + asv->kfc.cpu_dt_compat = "arm,cortex-a7";
> +
> + asv->opp_get_voltage = exynos5422_asv_opp_get_voltage;
> + asv->release = exynos5422_asv_release;
> +
> + return ret;
> +}
> diff --git a/drivers/soc/samsung/exynos5422-asv.h b/drivers/soc/samsung/exynos5422-asv.h
> new file mode 100644
> index 000000000000..f0d9107d6d0a
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos5422-asv.h
> @@ -0,0 +1,25 @@
> +// SPDX-License-Identifier: GPL-2.0

/**/ needed

> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.

Date

Best regards,
Krzysztof

> + * http://www.samsung.com/
> + *
> + * Samsung Exynos 5422 SoC Adaptive Supply Voltage support
> + */
> +
> +#ifndef __EXYNOS5422_ASV_H
> +#define __EXYNOS5422_ASV_H
> +
> +#include <linux/errno.h>
> +
> +struct exynos_asv;
> +
> +#ifdef CONFIG_EXYNOS_ASV_ARM
> +int exynos5422_asv_init(struct exynos_asv *asv);
> +#else
> +static inline int exynos5422_asv_init(struct exynos_asv *asv)
> +{
> + return -ENOTSUPP;
> +}
> +#endif
> +
> +#endif /* __EXYNOS5422_ASV_H */
> --
> 2.17.1
>

2019-04-09 17:41:34

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH RFC 4/8] soc: samsung: Add Exynos Adaptive Supply Voltage driver

On 4/5/19 12:24, Krzysztof Kozlowski wrote:
> I have a lot of minor nits all around and few more architecture-like comments.
>
> I think this should be a driver. You initialize it quite late and it
> is required by other drivers (cpufreq, devfreq), not by core.

Thanks for your comments, it helped me to finally get around and convert
this code to proper driver. The advantage is that it can be more
reliably ensured that the ASV driver updates OPPs properly after they
have been parsed from DT by cpufreq-dt or other drivers. And if we
add support for the Body Bias through regulator API it would be easier
to acquire the regulator resource, i.e. deferred probing could ensure
proper driver probe ordering.

> I would also prefer it to be slightly more generic. I mean, now you
> get the tables from "samsung,exynos-asv-v1" node and then, depending
> on many different compatibles, you do this or that. If it is
> samsung,exynos5800, you call 542x code. If it is hardkernel, you
> assume it is bin2. This will be not easily portable to other Exynos
> chips and other boards (e.g. you need to update the driver for new
> board which is forced to be in bin2).

The bin2 part for Odroid XU3 Lite is really a hack and I wish it was
not there. It seems there is not enough data fused in the SoC to
properly detect chips used on XU3 Lite.

> Instead all this information should come from chipid and/or DT. I

Perhaps we could try to be more generic but I'm afraid in practice
we will need to have some logic coded in the driver per each SoC type
anyway. We could probably add DT property in chipid node to provide
missing data that is normally read from CHIPID registers. The BIN2
flag is really about forcing specific ASV table. The "special group"
quirk means different thing for each SoC type, in case of exynos5422
it's selecting different method of the ASV group decoding.
It's a bit hard to try to put anything in DT with sparse or missing
documentation of such quirks.

> could imagine that the device binds to ASV node and parses its
> properties. Optionally it could bind to chipid... but then you would

The ASV node on older SoCs doesn't correspond to real hardware so
we shouldn't try to bind drivers to it I'd say. The chipid node
seems a better alternative to me.
I'm thinking about dropping 'asv' node completely. But then the
table sub-nodes would need to be put into chipid node.

> have two devices on same node. Then depending on the of_device_id
> match, you have all necessary static configuration data (the same as
> PMU driver or all other typical drivers). Dynamic data you read from
> chip id.

I will post next version of the patch series and we could continue
discussion from there, I have switched to of_device_id matching but
left per SoC init function.

> On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>>
>> The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
>> operating points of devices in order to better match actual capabilities
>> of the hardware and optimize power consumption.
>>
>> This patch adds common code for parsing the ASV tables from devicetree
>> and updating CPU OPPs.
>>
>> Also support for Exynos5422/5800 SoC is added, the Exynos5422 specific part
>> of the patch is partially based on code from
>> https://github.com/hardkernel/linux repository, branch odroidxu4-4.14.y,
>> files: arch/arm/mach-exynos/exynos5422-asv.[ch].
>>
>> Tested on Odroid XU3, XU4, XU3 Lite.
>>
>> Signed-off-by: Sylwester Nawrocki <[email protected]>
>> ---

>> diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
>> index 2905f5262197..4d121984f71a 100644
>> --- a/drivers/soc/samsung/Kconfig
>> +++ b/drivers/soc/samsung/Kconfig
>> @@ -7,6 +7,17 @@ menuconfig SOC_SAMSUNG
>>
>> if SOC_SAMSUNG
>>
>> +config EXYNOS_ASV
>> + bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST
>> + depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
>
> Why it cannot be compile tested outside of ARM? The PMU driver has
> this constraint because of asm/cputype.h but you probably do not need
> it.

Yes, it's not needed, I will drop the (ARM || ARM64) part in next iteration.

>> diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
>> new file mode 100644
>> index 000000000000..60532c7eb3aa
>> --- /dev/null
>> +++ b/drivers/soc/samsung/exynos-asv.c
>> @@ -0,0 +1,279 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
>
> Since it is first publish date, copyright should be only 2019....
> unless this was copied from hardkernel repo but then original
> copyright should be included as well.

I will change it to 2019. I have written code in this file from
scratch by myself. Some reused code is in exynos5422-asv.c, I will
copy the original copyright notice there, however it is same
Samsung's copyright notice, only with 2012 date.

--
Regards,
Sylwester

2019-04-11 07:41:53

by Anand Moon

[permalink] [raw]
Subject: Re: [PATCH RFC 8/8] ARM: dts: exynos: Add ASV tables for exynos5422/5800

Hi Sylwester,

As per my knowledge HK soc introduce this table to support
overclocking of cpufreq for Odroid XU3 XU4 family for boards.

ARM Cortex-A15 Quad CPU (Eagle) 1800 to 2000
ARM Cortex-A7 Quard CPU (Kingfisher) 1400 to 1500

For Exynos5422 below table
asv-table-[0-3] AVS range from 200 to 2100
asv-table-[100-103] AVS range from 200 to 1500.

Are these setting stable for this board to cover clock the cpu now.

Can you also enable support for this clk-exynos5420.c
For example exynos5800_eglclk_d and exynos5420_kfcclk_d table.

Also can you update exynos5420.dtsi following opp table
For example cluster_a15_opp_table and cluster_a7_opp_table opt binding.

To make this work synchronously with AVS.

Best Regards
-Anand

On Thu, 4 Apr 2019 at 22:55, Sylwester Nawrocki <[email protected]> wrote:
>
> This patch ASV (Adaptive Supply Voltage) table entries for
> Exynos5422/5800 SoC.
>
> Signed-off-by: Sylwester Nawrocki <[email protected]>
> ---
> arch/arm/boot/dts/exynos5.dtsi | 2 +-
> arch/arm/boot/dts/exynos5800.dtsi | 207 ++++++++++++++++++++++++++++++
> 2 files changed, 208 insertions(+), 1 deletion(-)
>
> diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
> index 67f9b4504a42..22eb951c614c 100644
> --- a/arch/arm/boot/dts/exynos5.dtsi
> +++ b/arch/arm/boot/dts/exynos5.dtsi
> @@ -35,7 +35,7 @@
> #size-cells = <1>;
> ranges;
>
> - chipid@10000000 {
> + chipid: chipid@10000000 {
> compatible = "samsung,exynos4210-chipid";
> reg = <0x10000000 0x100>;
> };
> diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
> index 57d3b319fd65..5358865f5c0b 100644
> --- a/arch/arm/boot/dts/exynos5800.dtsi
> +++ b/arch/arm/boot/dts/exynos5800.dtsi
> @@ -16,6 +16,213 @@
> compatible = "samsung,exynos5800", "samsung,exynos5";
> };
>
> +&chipid {
> + asv {
> + compatible = "samsung,exynos-asv-v1";
> + asv-table-0 {
> + /* ARM 0, 1 */
> + samsung,asv-table-size = <20 15>;
> + samsung,asv-table-id = <0x0>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
> + <2000 1312500 1312500 1300000 1287500 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
> + <1900 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1162500 1150000 1137500 1125000 1112500>,
> + <1800 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1112500 1100000 1087500 1075000 1062500>,
> + <1700 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1075000 1062500 1050000 1037500 1025000>,
> + <1600 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1037500 1025000 1012500 1000000 987500>,
> + <1500 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 1000000 987500 975000 962500 950000>,
> + <1400 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 975000 962500 950000 937500 925000>,
> + <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
> + <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
> + <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
> + <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <700 900000>,
> + <600 900000>,
> + <500 900000>,
> + <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> + asv-table-2 {
> + /* ARM 2 */
> + samsung,asv-table-size = <20 15>;
> + samsung,asv-table-id = <0x2>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
> + <2000 1312500 1312500 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
> + <1900 1262500 1250000 1250000 1237500 1212500 1200000 1187500 1175000 1162500 1175000 1162500 1150000 1137500 1125000>,
> + <1800 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1125000 1112500 1100000 1087500 1075000>,
> + <1700 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1087500 1075000 1062500 1050000 1037500>,
> + <1600 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1050000 1037500 1025000 1012500 1000000>,
> + <1500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
> + <1400 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 987500 975000 962500 950000 937500>,
> + <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
> + <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
> + <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
> + <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <700 900000>,
> + <600 900000>,
> + <500 900000>,
> + <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> + asv-table-3 {
> + /* ARM 3 */
> + samsung,asv-table-size = <20 15>;
> + samsung,asv-table-id = <0x3>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
> + <2000 1312500 1312500 1300000 1287500 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
> + <1900 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1175000 1162500 1150000 1137500 1125000>,
> + <1800 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1125000 1112500 1100000 1087500 1075000>,
> + <1700 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1087500 1075000 1062500 1050000 1037500>,
> + <1600 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1050000 1037500 1025000 1012500 1000000>,
> + <1500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
> + <1400 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 987500 975000 962500 950000 937500>,
> + <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
> + <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
> + <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
> + <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <700 900000>,
> + <600 900000>,
> + <500 900000>,
> + <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> +
> + asv-table-4 {
> + /* ARM BIN2 */
> + samsung,asv-table-size = <17 15>;
> + samsung,asv-table-id = <0x4>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <1800 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1150000 1137500 1125000 1112500 1100000>,
> + <1700 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1112500 1100000 1087500 1075000 1062500>,
> + <1600 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1075000 1062500 1050000 1037500 1025000>,
> + <1500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1037500 1025000 1012500 1000000 987500>,
> + <1400 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
> + <1300 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 1000000 987500 975000 962500 950000>,
> + <1200 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 975000 962500 950000 937500 925000>,
> + <1100 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 950000 937500 925000 912500 900000>,
> + <1000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 925000 912500 900000 900000 900000>,
> + < 900 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> + < 800 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 700 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <600 900000>,
> + <500 900000>,
> + <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> +
> +
> + asv-table-100 {
> + /* KFC 0, 1 */
> + samsung,asv-table-size = <14 15>;
> + samsung,asv-table-id = <0x100>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
> + <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
> + <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
> + <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
> + <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
> + <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
> + < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
> + < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
> + < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> + < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> +
> + asv-table-102 {
> + /* KFC 2 */
> + samsung,asv-table-size = <14 15>;
> + samsung,asv-table-id = <0x102>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
> + <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
> + <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
> + <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
> + <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
> + <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
> + < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
> + < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
> + < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> + < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> +
> + asv-table-103 {
> + /* KFC 3 */
> + samsung,asv-table-size = <14 15>;
> + samsung,asv-table-id = <0x103>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
> + <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
> + <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
> + <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
> + <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
> + <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
> + < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
> + < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
> + < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> + < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <400 900000>,
> + <300 900000>,
> + <200 900000>;
> + };
> +
> + asv-table-104 {
> + /* KFC BIN2 */
> + samsung,asv-table-size = <12 15>;
> + samsung,asv-table-id = <0x104>;
> + samsung,asv-data =
> + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> + <1300 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500>,
> + <1200 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500>,
> + <1100 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000>,
> + <1000 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500>,
> + < 900 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000>,
> + < 800 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000>,
> + < 700 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000>,
> + < 600 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 500 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> + < 400 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> + /* ASV0...13 */
> + samsung,asv-common-data = <300 900000>,
> + <200 900000>;
> + };
> + };
> +};
> +
> &clock {
> compatible = "samsung,exynos5800-clock";
> };
> --
> 2.17.1
>

2019-04-11 08:51:37

by Willy Wolff

[permalink] [raw]
Subject: Re: [PATCH RFC 8/8] ARM: dts: exynos: Add ASV tables for exynos5422/5800

Hi Anand,

I'm using this frequencies on the board since 3 years, without any stability
issues. The kind of worklaod used is intensive CPU-bound benchmarks running
for 20 mins at least in order to stress the system, I'm studying schedulability
under high thermal constraints.

So, I would say these frequencies are safe by experience.

Best Regards,
Willy


On Thu, Apr 11, 2019 at 01:09:04PM +0530, Anand Moon wrote:
> Hi Sylwester,
>
> As per my knowledge HK soc introduce this table to support
> overclocking of cpufreq for Odroid XU3 XU4 family for boards.
>
> ARM Cortex-A15 Quad CPU (Eagle) 1800 to 2000
> ARM Cortex-A7 Quard CPU (Kingfisher) 1400 to 1500
>
> For Exynos5422 below table
> asv-table-[0-3] AVS range from 200 to 2100
> asv-table-[100-103] AVS range from 200 to 1500.
>
> Are these setting stable for this board to cover clock the cpu now.
>
> Can you also enable support for this clk-exynos5420.c
> For example exynos5800_eglclk_d and exynos5420_kfcclk_d table.
>
> Also can you update exynos5420.dtsi following opp table
> For example cluster_a15_opp_table and cluster_a7_opp_table opt binding.
>
> To make this work synchronously with AVS.
>
> Best Regards
> -Anand
>
> On Thu, 4 Apr 2019 at 22:55, Sylwester Nawrocki <[email protected]> wrote:
> >
> > This patch ASV (Adaptive Supply Voltage) table entries for
> > Exynos5422/5800 SoC.
> >
> > Signed-off-by: Sylwester Nawrocki <[email protected]>
> > ---
> > arch/arm/boot/dts/exynos5.dtsi | 2 +-
> > arch/arm/boot/dts/exynos5800.dtsi | 207 ++++++++++++++++++++++++++++++
> > 2 files changed, 208 insertions(+), 1 deletion(-)
> >
> > diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
> > index 67f9b4504a42..22eb951c614c 100644
> > --- a/arch/arm/boot/dts/exynos5.dtsi
> > +++ b/arch/arm/boot/dts/exynos5.dtsi
> > @@ -35,7 +35,7 @@
> > #size-cells = <1>;
> > ranges;
> >
> > - chipid@10000000 {
> > + chipid: chipid@10000000 {
> > compatible = "samsung,exynos4210-chipid";
> > reg = <0x10000000 0x100>;
> > };
> > diff --git a/arch/arm/boot/dts/exynos5800.dtsi b/arch/arm/boot/dts/exynos5800.dtsi
> > index 57d3b319fd65..5358865f5c0b 100644
> > --- a/arch/arm/boot/dts/exynos5800.dtsi
> > +++ b/arch/arm/boot/dts/exynos5800.dtsi
> > @@ -16,6 +16,213 @@
> > compatible = "samsung,exynos5800", "samsung,exynos5";
> > };
> >
> > +&chipid {
> > + asv {
> > + compatible = "samsung,exynos-asv-v1";
> > + asv-table-0 {
> > + /* ARM 0, 1 */
> > + samsung,asv-table-size = <20 15>;
> > + samsung,asv-table-id = <0x0>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
> > + <2000 1312500 1312500 1300000 1287500 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
> > + <1900 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1162500 1150000 1137500 1125000 1112500>,
> > + <1800 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1112500 1100000 1087500 1075000 1062500>,
> > + <1700 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1075000 1062500 1050000 1037500 1025000>,
> > + <1600 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1037500 1025000 1012500 1000000 987500>,
> > + <1500 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 1000000 987500 975000 962500 950000>,
> > + <1400 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 975000 962500 950000 937500 925000>,
> > + <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
> > + <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
> > + <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
> > + <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <700 900000>,
> > + <600 900000>,
> > + <500 900000>,
> > + <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > + asv-table-2 {
> > + /* ARM 2 */
> > + samsung,asv-table-size = <20 15>;
> > + samsung,asv-table-id = <0x2>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
> > + <2000 1312500 1312500 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
> > + <1900 1262500 1250000 1250000 1237500 1212500 1200000 1187500 1175000 1162500 1175000 1162500 1150000 1137500 1125000>,
> > + <1800 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1125000 1112500 1100000 1087500 1075000>,
> > + <1700 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1087500 1075000 1062500 1050000 1037500>,
> > + <1600 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1050000 1037500 1025000 1012500 1000000>,
> > + <1500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
> > + <1400 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 987500 975000 962500 950000 937500>,
> > + <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
> > + <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
> > + <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
> > + <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <700 900000>,
> > + <600 900000>,
> > + <500 900000>,
> > + <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > + asv-table-3 {
> > + /* ARM 3 */
> > + samsung,asv-table-size = <20 15>;
> > + samsung,asv-table-id = <0x3>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <2100 1362500 1362500 1350000 1337500 1325000 1312500 1300000 1275000 1262500 1250000 1237500 1225000 1212500 1200000>,
> > + <2000 1312500 1312500 1300000 1287500 1275000 1262500 1250000 1237500 1225000 1237500 1225000 1212500 1200000 1187500>,
> > + <1900 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1175000 1162500 1150000 1137500 1125000>,
> > + <1800 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1125000 1112500 1100000 1087500 1075000>,
> > + <1700 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1087500 1075000 1062500 1050000 1037500>,
> > + <1600 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1050000 1037500 1025000 1012500 1000000>,
> > + <1500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
> > + <1400 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 987500 975000 962500 950000 937500>,
> > + <1300 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 962500 950000 937500 925000 912500>,
> > + <1200 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 937500 925000 912500 900000 900000>,
> > + <1100 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000>,
> > + <1000 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 900 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 800 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <700 900000>,
> > + <600 900000>,
> > + <500 900000>,
> > + <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > +
> > + asv-table-4 {
> > + /* ARM BIN2 */
> > + samsung,asv-table-size = <17 15>;
> > + samsung,asv-table-id = <0x4>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <1800 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1150000 1137500 1125000 1112500 1100000>,
> > + <1700 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1112500 1100000 1087500 1075000 1062500>,
> > + <1600 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1075000 1062500 1050000 1037500 1025000>,
> > + <1500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1037500 1025000 1012500 1000000 987500>,
> > + <1400 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 1012500 1000000 987500 975000 962500>,
> > + <1300 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 1000000 987500 975000 962500 950000>,
> > + <1200 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 975000 962500 950000 937500 925000>,
> > + <1100 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 950000 937500 925000 912500 900000>,
> > + <1000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 925000 912500 900000 900000 900000>,
> > + < 900 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> > + < 800 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 700 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <600 900000>,
> > + <500 900000>,
> > + <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > +
> > +
> > + asv-table-100 {
> > + /* KFC 0, 1 */
> > + samsung,asv-table-size = <14 15>;
> > + samsung,asv-table-id = <0x100>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
> > + <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
> > + <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
> > + <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
> > + <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
> > + <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
> > + < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
> > + < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
> > + < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> > + < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > +
> > + asv-table-102 {
> > + /* KFC 2 */
> > + samsung,asv-table-size = <14 15>;
> > + samsung,asv-table-id = <0x102>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
> > + <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
> > + <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
> > + <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
> > + <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
> > + <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
> > + < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
> > + < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
> > + < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> > + < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > +
> > + asv-table-103 {
> > + /* KFC 3 */
> > + samsung,asv-table-size = <14 15>;
> > + samsung,asv-table-id = <0x103>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <1500 1300000 1300000 1300000 1287500 1287500 1287500 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500>,
> > + <1400 1275000 1262500 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500>,
> > + <1300 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500>,
> > + <1200 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500>,
> > + <1100 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000>,
> > + <1000 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500>,
> > + < 900 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000>,
> > + < 800 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000>,
> > + < 700 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000>,
> > + < 600 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 500 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <400 900000>,
> > + <300 900000>,
> > + <200 900000>;
> > + };
> > +
> > + asv-table-104 {
> > + /* KFC BIN2 */
> > + samsung,asv-table-size = <12 15>;
> > + samsung,asv-table-id = <0x104>;
> > + samsung,asv-data =
> > + /* ASV0 ASV1 ASV2 ASV3 ASV4 ASV5 ASV6 ASV7 ASV8 ASV9 ASV10 ASV11 ASV12 ASV13 */
> > + <1300 1250000 1237500 1225000 1212500 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500>,
> > + <1200 1200000 1187500 1175000 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500>,
> > + <1100 1162500 1150000 1137500 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000>,
> > + <1000 1125000 1112500 1100000 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500>,
> > + < 900 1087500 1075000 1062500 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000>,
> > + < 800 1050000 1037500 1025000 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000>,
> > + < 700 1012500 1000000 987500 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000>,
> > + < 600 975000 962500 950000 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 500 937500 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>,
> > + < 400 925000 912500 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000 900000>;
> > + /* ASV0...13 */
> > + samsung,asv-common-data = <300 900000>,
> > + <200 900000>;
> > + };
> > + };
> > +};
> > +
> > &clock {
> > compatible = "samsung,exynos5800-clock";
> > };
> > --
> > 2.17.1
> >

2019-04-23 10:51:37

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH RFC 4/8] soc: samsung: Add Exynos Adaptive Supply Voltage driver

On Thu, 4 Apr 2019 at 19:22, Sylwester Nawrocki <[email protected]> wrote:
>
> The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
> operating points of devices in order to better match actual capabilities
> of the hardware and optimize power consumption.
>
> This patch adds common code for parsing the ASV tables from devicetree
> and updating CPU OPPs.
>
> Also support for Exynos5422/5800 SoC is added, the Exynos5422 specific part
> of the patch is partially based on code from
> https://github.com/hardkernel/linux repository, branch odroidxu4-4.14.y,
> files: arch/arm/mach-exynos/exynos5422-asv.[ch].
>
> Tested on Odroid XU3, XU4, XU3 Lite.
>
> Signed-off-by: Sylwester Nawrocki <[email protected]>
> ---
> drivers/soc/samsung/Kconfig | 11 ++
> drivers/soc/samsung/Makefile | 3 +
> drivers/soc/samsung/exynos-asv.c | 279 +++++++++++++++++++++++++++
> drivers/soc/samsung/exynos-asv.h | 114 +++++++++++
> drivers/soc/samsung/exynos5422-asv.c | 209 ++++++++++++++++++++
> drivers/soc/samsung/exynos5422-asv.h | 25 +++
> 6 files changed, 641 insertions(+)
> create mode 100644 drivers/soc/samsung/exynos-asv.c
> create mode 100644 drivers/soc/samsung/exynos-asv.h
> create mode 100644 drivers/soc/samsung/exynos5422-asv.c
> create mode 100644 drivers/soc/samsung/exynos5422-asv.h
>
> diff --git a/drivers/soc/samsung/Kconfig b/drivers/soc/samsung/Kconfig
> index 2905f5262197..4d121984f71a 100644
> --- a/drivers/soc/samsung/Kconfig
> +++ b/drivers/soc/samsung/Kconfig
> @@ -7,6 +7,17 @@ menuconfig SOC_SAMSUNG
>
> if SOC_SAMSUNG
>
> +config EXYNOS_ASV
> + bool "Exynos Adaptive Supply Voltage support" if COMPILE_TEST
> + depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
> + depends on EXYNOS_CHIPID
> + select EXYNOS_ASV_ARM if ARM && ARCH_EXYNOS
> +
> +# There is no need to enable these drivers for ARMv8
> +config EXYNOS_ASV_ARM
> + bool "Exynos ASV ARMv7-specific driver extensions" if COMPILE_TEST
> + depends on EXYNOS_ASV
> +
> config EXYNOS_CHIPID
> bool "Exynos Chipid controller driver" if COMPILE_TEST
> depends on ARCH_EXYNOS || COMPILE_TEST
> diff --git a/drivers/soc/samsung/Makefile b/drivers/soc/samsung/Makefile
> index 3b6a8797416c..edd1d6ea064d 100644
> --- a/drivers/soc/samsung/Makefile
> +++ b/drivers/soc/samsung/Makefile
> @@ -1,5 +1,8 @@
> # SPDX-License-Identifier: GPL-2.0
>
> +obj-$(CONFIG_EXYNOS_ASV) += exynos-asv.o
> +obj-$(CONFIG_EXYNOS_ASV_ARM) += exynos5422-asv.o
> +
> obj-$(CONFIG_EXYNOS_CHIPID) += exynos-chipid.o
> obj-$(CONFIG_EXYNOS_PMU) += exynos-pmu.o
>
> diff --git a/drivers/soc/samsung/exynos-asv.c b/drivers/soc/samsung/exynos-asv.c
> new file mode 100644
> index 000000000000..60532c7eb3aa
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos-asv.c
> @@ -0,0 +1,279 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + * Author: Sylwester Nawrocki <[email protected]>
> + *
> + * Samsung Exynos SoC Adaptive Supply Voltage support
> + */
> +
> +#include <linux/cpu.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/pm_opp.h>
> +#include <linux/slab.h>
> +
> +#include "exynos-asv.h"
> +#include "exynos5422-asv.h"
> +#include "exynos5433-asv.h"
> +
> +#ifndef MHZ
> +#define MHZ 1000000U
> +#endif
> +
> +static struct exynos_asv *exynos_asv;
> +
> +int exynos_asv_parse_of_table(struct device_node *node,
> + struct exynos_asv_table *table,
> + int index)
> +{
> + u32 table_size, table_id = 0;
> + unsigned int len1, len2 = 0;
> + unsigned int num_cols, num_rows;
> + u32 tmp[20];
> + u32 *buf;
> + int ret;
> +
> + ret = of_property_read_u32(node, "samsung,asv-table-id",
> + &table_id);
> + if (ret < 0) {
> + pr_err("ASV: Missing table id in %pOF\n", node);
> + return ret;
> + }
> + table->id = table_id;
> +
> + if (index >= 0 && asv_table_to_index(table_id) != index)
> + return -EBADR;
> +
> + ret = of_property_read_u32_array(node, "samsung,asv-table-size",
> + tmp, 2);
> + if (ret < 0)
> + return ret;
> +
> + num_rows = tmp[0];
> + num_cols = tmp[1];
> + if (num_rows > EXYNOS_ASV_MAX_LEVELS ||
> + num_cols > (EXYNOS_ASV_MAX_GROUPS + 1)) {
> + pr_err("ASV: Unsupported ASV table size (%d x %d)\n",
> + num_rows, num_cols);
> + return -EINVAL;
> + }
> +
> + table_size = num_rows * num_cols;
> + buf = kcalloc(table_size, sizeof(u32), GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + ret = of_property_read_variable_u32_array(node, "samsung,asv-data",
> + buf, 0, table_size);
> + if (ret < 0)
> + goto err_free_buf;
> +
> + len1 = ret;
> +
> + if (ret < table_size) {
> + u32 *dst, *src;
> + ret = of_property_read_variable_u32_array(node,
> + "samsung,asv-common-data",
> + (u32 *)tmp, 0,
> + ARRAY_SIZE(tmp));
> + if (ret < 0) {
> + pr_err("ASV: Not enough data for table #%x (%d x %d)\n",
> + table_id, num_rows, num_cols);
> + goto err_free_buf;
> + }
> + len2 = ret;
> +
> + if (len1 + ((len2 / 2) * num_cols) > table_size) {
> + pr_err("ASV: Incorrect table %#x definition\n",
> + table_id);
> + ret = -EINVAL;
> + goto err_free_buf;
> + }
> + /*
> + * Copy data common to all ASV levels to first and second column
> + * in the main buffer. We don't replicate data to further
> + * columns, instead they are left initialized to 0 (invalid,
> + * unused frequency value). We assume that users of the table
> + * will refer to voltage data in column 1 if 0 is encountered
> + * in any further column (2, 3,...).
> + */
> + dst = buf + len1;
> + src = tmp;
> +
> + while (len2 >= 2) {
> + memcpy(dst, src, 2 * sizeof(u32));
> + dst += num_cols;
> + src += 2;
> + len2 -= 2;
> + }
> + }
> +
> + table->num_cols = num_cols;
> + table->num_rows = num_rows;
> + table->buf = buf;
> + return 0;
> +
> +err_free_buf:
> + kfree(buf);
> + return ret;
> +}
> +
> +int exynos_asv_parse_cpu_tables(struct exynos_asv *asv, struct device_node *np,
> + int table_index)
> +{
> + struct exynos_asv_subsys *subsys;
> + struct exynos_asv_table table;
> + struct device_node *child;
> + int ret;
> +
> + for_each_child_of_node(np, child) {
> + ret = exynos_asv_parse_of_table(child, &table, table_index);
> + if (ret < 0) {
> + if (ret == -EBADR)
> + continue;
> + of_node_put(child);
> + return ret;
> + }
> +
> + pr_debug("%s: Matching table: id: %#x at %pOF\n",
> + __func__, table.id, child);
> +
> + switch(asv_table_to_subsys_id(table.id)) {
> + case EXYNOS_ASV_SUBSYS_ID_ARM:
> + subsys = &asv->arm;
> + break;
> + case EXYNOS_ASV_SUBSYS_ID_KFC:
> + subsys = &asv->kfc;
> + break;
> + default:
> + of_node_put(child);
> + return -EINVAL;
> + }
> +
> + subsys->num_asv_levels = table.num_rows;
> + subsys->num_asv_groups = table.num_cols - 1;
> + subsys->table = table;
> + subsys->id = asv_table_to_subsys_id(table.id);
> + }
> +
> + return 0;
> +}
> +
> +static int exynos_asv_update_cpu_opps(struct device *cpu)
> +{
> + struct exynos_asv_subsys *subsys = NULL;
> + struct dev_pm_opp *opp;
> + unsigned int opp_freq;
> + int i;
> +
> + if (of_device_is_compatible(cpu->of_node,
> + exynos_asv->arm.cpu_dt_compat))
> + subsys = &exynos_asv->arm;
> + else if (of_device_is_compatible(cpu->of_node,
> + exynos_asv->kfc.cpu_dt_compat))
> + subsys = &exynos_asv->kfc;
> +
> + if (!subsys)
> + return -EINVAL;
> +
> + for (i = 0; i < subsys->num_asv_levels; i++) {
> + unsigned int new_voltage;
> + unsigned int voltage;
> + int timeout = 1000;
> + int err;
> +
> + opp_freq = exynos_asv_opp_get_frequency(subsys, i);
> +
> + opp = dev_pm_opp_find_freq_exact(cpu, opp_freq * MHZ, true);
> + if (IS_ERR(opp)) {
> + pr_info("%s cpu%d opp%d, freq: %u missing\n",
> + __func__, cpu->id, i, opp_freq);
> +
> + continue;
> + }
> +
> + voltage = dev_pm_opp_get_voltage(opp);
> + new_voltage = exynos_asv->opp_get_voltage(subsys, i, voltage);
> + dev_pm_opp_put(opp);
> +
> + opp_freq *= MHZ;
> + dev_pm_opp_remove(cpu, opp_freq);
> +
> + while (--timeout) {
> + opp = dev_pm_opp_find_freq_exact(cpu, opp_freq, true);
> + if (IS_ERR(opp))
> + break;
> + dev_pm_opp_put(opp);
> + msleep(1);
> + }
> +
> + err = dev_pm_opp_add(cpu, opp_freq, new_voltage);
> + if (err < 0)
> + pr_err("%s: Failed to add OPP %u Hz/%u uV for cpu%d\n",
> + __func__, opp_freq, new_voltage, cpu->id);
> + }
> +
> + return 0;
> +}
> +
> +static int exynos_asv_update_opps(void)
> +{
> + struct opp_table *last_opp_table = NULL;
> + struct device *cpu;
> + int ret, cpuid;
> +
> + for_each_possible_cpu(cpuid) {
> + struct opp_table *opp_table;
> +
> + cpu = get_cpu_device(cpuid);
> + if (!cpu)
> + continue;
> +
> + opp_table = dev_pm_opp_get_opp_table(cpu);
> + if (IS_ERR(opp_table))
> + continue;
> +
> + if (!last_opp_table || opp_table != last_opp_table) {
> + last_opp_table = opp_table;
> +
> + ret = exynos_asv_update_cpu_opps(cpu);
> + if (ret < 0)
> + pr_err("%s: Couldn't udate OPPs for cpu%d\n",
> + __func__, cpuid);
> + }
> +
> + dev_pm_opp_put_opp_table(opp_table);
> + }
> +
> + return 0;
> +}
> +
> +static int __init exynos_asv_init(void)
> +{
> + int ret;
> +
> + exynos_asv = kcalloc(1, sizeof(struct exynos_asv), GFP_KERNEL);
> + if (!exynos_asv)
> + return -ENOMEM;
> +
> + if (of_machine_is_compatible("samsung,exynos5800") ||
> + of_machine_is_compatible("samsung,exynos5420"))
> + ret = exynos5422_asv_init(exynos_asv);
> + else
> + return 0;
> +
> + if (ret < 0)
> + return ret;
> +
> + ret = exynos_asv_update_opps();
> +
> + if (exynos_asv->release)
> + exynos_asv->release(exynos_asv);
> +
> + return ret;
> +}
> +late_initcall(exynos_asv_init)
> diff --git a/drivers/soc/samsung/exynos-asv.h b/drivers/soc/samsung/exynos-asv.h
> new file mode 100644
> index 000000000000..3444b361e5e3
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos-asv.h
> @@ -0,0 +1,114 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + * Author: Sylwester Nawrocki <[email protected]>
> + *
> + * Samsung Exynos SoC Adaptive Supply Voltage support
> + */
> +#ifndef __EXYNOS_ASV_H
> +#define __EXYNOS_ASV_H
> +
> +#define EXYNOS_ASV_MAX_GROUPS 16
> +#define EXYNOS_ASV_MAX_LEVELS 24
> +
> +#define EXYNOS_ASV_TABLE_INDEX_MASK (0xff)
> +#define EXYNOS_ASV_SUBSYS_ID_MASK (0xff << 8)
> +
> +#define asv_table_to_subsys_id(_id) ((_id >> 8) & 0xff)
> +#define asv_table_to_index(_id) ((_id) & 0xff)
> +
> +#define EXYNOS_ASV_SUBSYS_ID_ARM 0x0
> +#define EXYNOS_ASV_SUBSYS_ID_EGL EXYNOS_ASV_SUBSYS_ID_ARM
> +#define EXYNOS_ASV_SUBSYS_ID_KFC 0x1
> +#define EXYNOS_ASV_SUBSYS_ID_INT 0x2
> +#define EXYNOS_ASV_SUBSYS_ID_MIF 0x3
> +#define EXYNOS_ASV_SUBSYS_ID_G3D 0x4
> +#define EXYNOS_ASV_SUBSYS_ID_CAM 0x5
> +#define EXYNOS_ASV_SUBSYS_ID_MAX 0x6
> +
> +struct device_node;
> +
> +/* HPM, IDS values to select target group */
> +struct asv_limit_entry {
> + unsigned int hpm;
> + unsigned int ids;
> +};
> +
> +struct exynos_asv_table {
> + unsigned int num_rows;
> + unsigned int num_cols;
> + unsigned int id;
> + u32 *buf;
> +};
> +
> +struct exynos_asv_subsys {
> + int id;
> + char *cpu_dt_compat;
> +
> + unsigned int base_volt;
> + unsigned int num_asv_levels;
> + unsigned int num_asv_groups;
> + unsigned int offset_volt_h;
> + unsigned int offset_volt_l;
> + struct exynos_asv_table table;
> +};
> +
> +struct exynos_asv {
> + struct device_node *chipid_node;
> + struct exynos_asv_subsys arm;
> + struct exynos_asv_subsys kfc;
> +
> + int (*opp_get_voltage)(struct exynos_asv_subsys *subs, int level,
> + unsigned int voltage);
> + void (*release)(struct exynos_asv *asv);
> +
> + unsigned int group;
> + unsigned int table;
> +
> + /* TODO: Move member fields below to SoC type specific data structure */
> + unsigned int is_bin2;
> + unsigned int is_special_lot;
> +};
> +
> +static inline u32 __exynos_asv_get_item(struct exynos_asv_table *table,
> + unsigned int row, unsigned int col)
> +{
> + return table->buf[row * (table->num_cols) + col];
> +}
> +
> +static inline u32 exynos_asv_opp_get_frequency(struct exynos_asv_subsys *subsys,
> + unsigned int index)
> +{
> + return __exynos_asv_get_item(&subsys->table, index, 0);
> +}
> +/**
> + * exynos_asv_parse_of_table - Parse ASV table from devicetree
> + *
> + * @node: DT node containing the table
> + * @table: The parsed table data
> + * @index: Used to select table with specific index to parse, if >= 0.
> + * This argument is ignored if the value is less than 0.
> + *
> + * Returns: 0 on success, or negative value on failure. EBADR is returned
> + * when @index is >= 0 but the index value of the parsed table ID is different
> + * than @index.
> + */
> +int exynos_asv_parse_of_table(struct device_node *node,
> + struct exynos_asv_table *table,
> + int index);
> +
> +/**
> + * exynos_asv_parse_cpu_tables - Parse ARM and KFC ASV tables from DT
> + *
> + * @asv: data structure to store the parsed data to
> + * @node: DT node containing the tables
> + * @index: Used to select table with specific index to parse, if >= 0.
> + * This argument is ignored if the value is less than 0.
> + *
> + * Returns: 0 on success, or negative value on failure.
> + */
> +int exynos_asv_parse_cpu_tables(struct exynos_asv *asv, struct device_node *np,
> + int table_index);
> +
> +#endif /* __EXYNOS_ASV_H */
> diff --git a/drivers/soc/samsung/exynos5422-asv.c b/drivers/soc/samsung/exynos5422-asv.c
> new file mode 100644
> index 000000000000..f0b7bdd873a9
> --- /dev/null
> +++ b/drivers/soc/samsung/exynos5422-asv.c
> @@ -0,0 +1,209 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2018 - 2019 Samsung Electronics Co., Ltd.
> + * http://www.samsung.com/
> + *
> + * Samsung Exynos 5422 SoC Adaptive Supply Voltage support
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/init.h>
> +#include <linux/of.h>
> +#include <linux/slab.h>
> +
> +#include "exynos-asv.h"
> +#include "exynos-chipid.h"
> +
> +#define EXYNOS5422_NUM_ASV_GROUPS 14
> +
> +static struct exynos_asv *exynos_asv;
> +
> +static int exynos5422_asv_get_table(void)
> +{
> + unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);

One more thought: you read this register multiple times in the same
function. I think it is not needed - just read once, store the value
and use the helpers to parse it.

Best regards,
Krzysztof

2019-04-24 08:14:09

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH RFC 4/8] soc: samsung: Add Exynos Adaptive Supply Voltage driver

On 4/23/19 12:50, Krzysztof Kozlowski wrote:
>> +static int exynos5422_asv_get_table(void)
>> +{
>> + unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
>
> One more thought: you read this register multiple times in the same
> function. I think it is not needed - just read once, store the value
> and use the helpers to parse it.

Yes, I have noticed that as well. I'm not sure though if it is worth
to additionally cache registers manually like this when we use the
regmap. I have already converted that code to use the regmap API for
v2. And these are barely few registers reads at the driver
initialization time, not any hot path.

--
Thanks,
Sylwester

2019-04-24 08:22:42

by Krzysztof Kozlowski

[permalink] [raw]
Subject: Re: [PATCH RFC 4/8] soc: samsung: Add Exynos Adaptive Supply Voltage driver

On Wed, 24 Apr 2019 at 10:10, Sylwester Nawrocki <[email protected]> wrote:
>
> On 4/23/19 12:50, Krzysztof Kozlowski wrote:
> >> +static int exynos5422_asv_get_table(void)
> >> +{
> >> + unsigned int reg = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
> >
> > One more thought: you read this register multiple times in the same
> > function. I think it is not needed - just read once, store the value
> > and use the helpers to parse it.
>
> Yes, I have noticed that as well. I'm not sure though if it is worth
> to additionally cache registers manually like this when we use the
> regmap. I have already converted that code to use the regmap API for
> v2. And these are barely few registers reads at the driver
> initialization time, not any hot path.

By default regmap does not use caching so there is no benefit out of
it. In the same time reading with regmap involves its layer of
abstraction with locks, indirect calls etc... I agree that there is no
point for implementing specific "caching" but with the same code
readability/simplicity you can have it without multiple regmap
accesses one after another. Consider this:
unsigned int pkgid = exynos_chipid_read(EXYNOS_CHIPID_REG_PKG_ID);
asv->table = exynos5422_asv_get_table(pkgid);
asv->is_bin2 = exynos5422_asv_check_bin2(pkgid);
(and probably renaming the helpers)
The code is equivalent. The same readability.

Best regards,
Krzysztof

2019-04-29 17:24:56

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH RFC 3/8] dt-bindings: exynos: Add ASV tables binding documentation

On Thu, Apr 04, 2019 at 07:17:30PM +0200, Sylwester Nawrocki wrote:
> This patch adds documentation of the Exynos ASV (Adaptive Voltage Supply)
> tables DT binding.
>
> Signed-off-by: Sylwester Nawrocki <[email protected]>
> ---
> .../devicetree/bindings/arm/samsung/asv.txt | 76 +++++++++++++++++++
> 1 file changed, 76 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/arm/samsung/asv.txt
>
> diff --git a/Documentation/devicetree/bindings/arm/samsung/asv.txt b/Documentation/devicetree/bindings/arm/samsung/asv.txt
> new file mode 100644
> index 000000000000..0db907263a91
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/arm/samsung/asv.txt
> @@ -0,0 +1,76 @@
> +Exynos Adaptive Supply Voltage (ASV) tables
> +-------------------------------------------
> +
> +The Adaptive Supply Voltage (ASV) on Exynos SoCs is a technique of adjusting
> +operating points, i.e. the power supply voltage for given clock frequency,
> +in order to better match actual capabilities of the hardware and optimize power
> +consumption. This applies to subsystem of the SoC like: CPU clusters, GPU,
> +the memory controller or camera ISP. During production process the SoC chip
> +is assigned to one of several bins (ASV groups) and the group information
> +is encoded in the SoC CHIPID block registers and/or OTP memory. This information
> +is then used by the OS to select more finely matching operating points for
> +devices.

We already have OPP tables defined for QCom CPUs to do speed bining, and
I just reviewed something from Allwinner for similar purposes. We can't
have each vendor doing their own thing here.

Rob

2019-07-18 14:03:26

by Sylwester Nawrocki

[permalink] [raw]
Subject: Re: [PATCH RFC 3/8] dt-bindings: exynos: Add ASV tables binding documentation

On 4/29/19 19:23, Rob Herring wrote:
> We already have OPP tables defined for QCom CPUs to do speed bining, and
> I just reviewed something from Allwinner for similar purposes. We can't
> have each vendor doing their own thing here.

I tried that opp-supported-hw bitmask approach but number of OPP DT nodes
was rather high, around 200 per CPU cluster. So I moved OPP tables to
the driver. I'm going to post next version of the patch set soon.

--
Regards,
Sylwester