1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-03-09 15:40:20 +00:00

Add kernel 6.1 support on r7800

This commit is contained in:
Ycarus (Yannick Chabanois) 2023-05-19 10:10:28 +02:00
parent 49e5717c77
commit 223edd7f86
61 changed files with 12457 additions and 1 deletions

View file

@ -0,0 +1,67 @@
From 9c896e9fc2ef1209e4a56d8c9fdd183847c2c814 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 18 Oct 2022 22:02:46 +0200
Subject: [PATCH] ARM: mach-qcom: fix support for ipq806x
Add a specific config flag for Qcom IPQ806x as this SoC can't use
AUTO_ZRELADDR and require the PHYS_OFFSET set to 0x42000000.
This is needed as some legacy board (or some wrongly configured
bootloader) pass the wrong memory map and doesn't exclude the first
~20MB of RAM reserved for the hardware network accellerators.
With this change we can correctly support each board and prevent any
kind of misconfiguration done by the OEM.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
arch/arm/Kconfig | 3 ++-
arch/arm/mach-qcom/Kconfig | 13 +++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 1af63e17b4ad..0818d35973ad 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -282,6 +282,7 @@ config PHYS_OFFSET
default 0x30000000 if ARCH_S3C24XX
default 0xa0000000 if ARCH_IOP32X || ARCH_PXA
default 0xc0000000 if ARCH_EP93XX || ARCH_SA1100
+ default 0x42000000 if ARCH_IPQ806X
default 0
help
Please provide the physical address corresponding to the
@@ -1701,7 +1702,7 @@ config CRASH_DUMP
config AUTO_ZRELADDR
bool "Auto calculation of the decompressed kernel image address" if !ARCH_MULTIPLATFORM
- default !(ARCH_FOOTBRIDGE || ARCH_RPC || ARCH_SA1100)
+ default !(ARCH_FOOTBRIDGE || ARCH_RPC || ARCH_SA1100 || ARCH_IPQ806X)
help
ZRELADDR is the physical address where the decompressed kernel
image will be placed. If AUTO_ZRELADDR is selected, the address
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 12a812e61c16..b11b6e391ff0 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -46,4 +46,17 @@ config ARCH_MDM9615
bool "Enable support for MDM9615"
select CLKSRC_QCOM
+config ARCH_IPQ806X
+ bool "Enable support for IPQ806x"
+ help
+ Enable support for the Qualcomm IPQ806x.
+
+ IPQ806x require special PHYS_OFFSET and can't use AUTO_ZRELADDR.
+ The first ~20MB of RAM is reserved for the hardware network accelerators,
+ and the bootloader removes this section from the layout passed from the
+ ATAGS (when used by some bootloader doesn't even do that).
+
+ To support every system and handle legacy systems, hardcode PHYS_OFFSET and
+ disable AUTO_ZRELADDR.
+
endif
--
2.37.2

View file

@ -0,0 +1,21 @@
From 4d8e29642661397a339ac3485f212c6360445421 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 9 Mar 2017 09:33:32 +0100
Subject: [PATCH 65/69] arm: override compiler flags
Signed-off-by: John Crispin <john@phrozen.org>
---
arch/arm/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -61,7 +61,7 @@ KBUILD_CFLAGS += $(call cc-option,-fno-i
# macro, but instead defines a whole series of macros which makes
# testing for a specific architecture or later rather impossible.
arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m
-arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -march=armv7-a
+arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -mcpu=cortex-a15
arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 -march=armv6
# Only override the compiler option if ARMv6. The ARMv6K extensions are
# always available in ARMv7

View file

@ -0,0 +1,210 @@
From 71270226b14733a4b1f2cde58ea9265caa50b38d Mon Sep 17 00:00:00 2001
From: Adrian Panella <ianchi74@outlook.com>
Date: Thu, 9 Mar 2017 09:37:17 +0100
Subject: [PATCH 67/69] generic: Mangle bootloader's kernel arguments
The command-line arguments provided by the boot loader will be
appended to a new device tree property: bootloader-args.
If there is a property "append-rootblock" in DT under /chosen
and a root= option in bootloaders command line it will be parsed
and added to DT bootargs with the form: <append-rootblock>XX.
Only command line ATAG will be processed, the rest of the ATAGs
sent by bootloader will be ignored.
This is usefull in dual boot systems, to get the current root partition
without afecting the rest of the system.
Signed-off-by: Adrian Panella <ianchi74@outlook.com>
---
arch/arm/Kconfig | 11 +++++
arch/arm/boot/compressed/atags_to_fdt.c | 72 ++++++++++++++++++++++++++++++++-
init/main.c | 16 ++++++++
3 files changed, 98 insertions(+), 1 deletion(-)
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1727,6 +1727,17 @@ config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEN
The command-line arguments provided by the boot loader will be
appended to the the device tree bootargs property.
+config ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
+ bool "Append rootblock parsing bootloader's kernel arguments"
+ help
+ The command-line arguments provided by the boot loader will be
+ appended to a new device tree property: bootloader-args.
+ If there is a property "append-rootblock" in DT under /chosen
+ and a root= option in bootloaders command line it will be parsed
+ and added to DT bootargs with the form: <append-rootblock>XX.
+ Only command line ATAG will be processed, the rest of the ATAGs
+ sent by bootloader will be ignored.
+
endchoice
config CMDLINE
--- a/arch/arm/boot/compressed/atags_to_fdt.c
+++ b/arch/arm/boot/compressed/atags_to_fdt.c
@@ -5,6 +5,8 @@
#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND)
#define do_extend_cmdline 1
+#elif defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+#define do_extend_cmdline 1
#else
#define do_extend_cmdline 0
#endif
@@ -69,6 +71,80 @@ static uint32_t get_cell_size(const void
return cell_size;
}
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+/**
+ * taken from arch/x86/boot/string.c
+ * local_strstr - Find the first substring in a %NUL terminated string
+ * @s1: The string to be searched
+ * @s2: The string to search for
+ */
+static char *local_strstr(const char *s1, const char *s2)
+{
+ size_t l1, l2;
+
+ l2 = strlen(s2);
+ if (!l2)
+ return (char *)s1;
+ l1 = strlen(s1);
+ while (l1 >= l2) {
+ l1--;
+ if (!memcmp(s1, s2, l2))
+ return (char *)s1;
+ s1++;
+ }
+ return NULL;
+}
+
+static char *append_rootblock(char *dest, const char *str, int len, void *fdt)
+{
+ char *ptr, *end, *tmp;
+ char *root="root=";
+ char *find_rootblock;
+ int i, l;
+ const char *rootblock;
+
+ find_rootblock = getprop(fdt, "/chosen", "find-rootblock", &l);
+ if(!find_rootblock)
+ find_rootblock = root;
+
+ //ARM doesn't have __HAVE_ARCH_STRSTR, so it was copied from x86
+ ptr = local_strstr(str, find_rootblock);
+
+ if(!ptr)
+ return dest;
+
+ end = strchr(ptr, ' ');
+ end = end ? (end - 1) : (strchr(ptr, 0) - 1);
+
+ // Some boards ubi.mtd=XX,ZZZZ, so let's check for '," too.
+ tmp = strchr(ptr, ',');
+
+ if(tmp)
+ end = end < tmp ? end : tmp - 1;
+
+ //find partition number (assumes format root=/dev/mtdXX | /dev/mtdblockXX | yy:XX | ubi.mtd=XX,ZZZZ )
+ for( i = 0; end >= ptr && *end >= '0' && *end <= '9'; end--, i++);
+ ptr = end + 1;
+
+ /* if append-rootblock property is set use it to append to command line */
+ rootblock = getprop(fdt, "/chosen", "append-rootblock", &l);
+ if(rootblock != NULL) {
+ if(*dest != ' ') {
+ *dest = ' ';
+ dest++;
+ len++;
+ }
+ if (len + l + i <= COMMAND_LINE_SIZE) {
+ memcpy(dest, rootblock, l);
+ dest += l - 1;
+ memcpy(dest, ptr, i);
+ dest += i;
+ }
+ }
+ return dest;
+}
+#endif
+
static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline)
{
char cmdline[COMMAND_LINE_SIZE];
@@ -88,12 +164,21 @@ static void merge_fdt_bootargs(void *fdt
/* and append the ATAG_CMDLINE */
if (fdt_cmdline) {
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+ //save original bootloader args
+ //and append ubi.mtd with root partition number to current cmdline
+ setprop_string(fdt, "/chosen", "bootloader-args", fdt_cmdline);
+ ptr = append_rootblock(ptr, fdt_cmdline, len, fdt);
+
+#else
len = strlen(fdt_cmdline);
if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) {
*ptr++ = ' ';
memcpy(ptr, fdt_cmdline, len);
ptr += len;
}
+#endif
}
*ptr = '\0';
@@ -168,7 +253,9 @@ int atags_to_fdt(void *atag_list, void *
else
setprop_string(fdt, "/chosen", "bootargs",
atag->u.cmdline.cmdline);
- } else if (atag->hdr.tag == ATAG_MEM) {
+ }
+#ifndef CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE
+ else if (atag->hdr.tag == ATAG_MEM) {
if (memcount >= sizeof(mem_reg_property)/4)
continue;
if (!atag->u.mem.size)
@@ -212,6 +299,10 @@ int atags_to_fdt(void *atag_list, void *
setprop(fdt, "/memory", "reg", mem_reg_property,
4 * memcount * memsize);
}
+#else
+
+ }
+#endif
return fdt_pack(fdt);
}
--- a/init/main.c
+++ b/init/main.c
@@ -113,6 +113,10 @@
#include <kunit/test.h>
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+#include <linux/of.h>
+#endif
+
static int kernel_init(void *);
extern void init_IRQ(void);
@@ -992,6 +996,18 @@ asmlinkage __visible void __init __no_sa
pr_notice("Kernel command line: %s\n", saved_command_line);
/* parameters may set static keys */
jump_label_init();
+
+#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_MANGLE)
+ //Show bootloader's original command line for reference
+ if(of_chosen) {
+ const char *prop = of_get_property(of_chosen, "bootloader-args", NULL);
+ if(prop)
+ pr_notice("Bootloader command line (ignored): %s\n", prop);
+ else
+ pr_notice("Bootloader command line not present\n");
+ }
+#endif
+
parse_early_param();
after_dashes = parse_args("Booting kernel",
static_command_line, __start___param,

View file

@ -0,0 +1,44 @@
From 8f68331e14dff9a101f2d0e1d6bec84a031f27ee Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 9 Mar 2017 11:03:18 +0100
Subject: [PATCH 69/69] arm: boot: add dts files
Signed-off-by: John Crispin <john@phrozen.org>
---
arch/arm/boot/dts/Makefile | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -956,8 +956,30 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-ipq4019-ap.dk04.1-c3.dtb \
qcom-ipq4019-ap.dk07.1-c1.dtb \
qcom-ipq4019-ap.dk07.1-c2.dtb \
+ qcom-ipq8062-wg2600hp3.dtb \
qcom-ipq8064-ap148.dtb \
qcom-ipq8064-rb3011.dtb \
+ qcom-ipq8064-c2600.dtb \
+ qcom-ipq8064-d7800.dtb \
+ qcom-ipq8064-db149.dtb \
+ qcom-ipq8064-ap161.dtb \
+ qcom-ipq8064-ea7500-v1.dtb \
+ qcom-ipq8064-ea8500.dtb \
+ qcom-ipq8064-g10.dtb \
+ qcom-ipq8064-r7500.dtb \
+ qcom-ipq8064-r7500v2.dtb \
+ qcom-ipq8064-unifi-ac-hd.dtb \
+ qcom-ipq8064-wg2600hp.dtb \
+ qcom-ipq8064-wpq864.dtb \
+ qcom-ipq8064-wxr-2533dhp.dtb \
+ qcom-ipq8065-nbg6817.dtb \
+ qcom-ipq8065-r7800.dtb \
+ qcom-ipq8065-rt4230w-rev6.dtb \
+ qcom-ipq8065-tr4400-v2.dtb \
+ qcom-ipq8065-xr500.dtb \
+ qcom-ipq8068-ecw5410.dtb \
+ qcom-ipq8068-mr42.dtb \
+ qcom-ipq8068-mr52.dtb \
qcom-msm8226-samsung-s3ve3g.dtb \
qcom-msm8660-surf.dtb \
qcom-msm8960-cdp.dtb \

View file

@ -0,0 +1,25 @@
From 5001f2e1a325b68dbf225bd17f69a4d3d975cca5 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Thu, 9 Mar 2017 09:31:44 +0100
Subject: [PATCH 61/69] mtd: "rootfs" conflicts with OpenWrt auto mounting
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/mtd/mtdpart.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -51,7 +51,11 @@ static struct mtd_info *allocate_partiti
/* allocate the partition structure */
child = kzalloc(sizeof(*child), GFP_KERNEL);
- name = kstrdup(part->name, GFP_KERNEL);
+ /* "rootfs" conflicts with OpenWrt auto mounting */
+ if (mtd_type_is_nand(parent) && !strcmp(part->name, "rootfs"))
+ name = "ubi";
+ else
+ name = kstrdup(part->name, GFP_KERNEL);
if (!name || !child) {
printk(KERN_ERR"memory allocation error while creating partitions for \"%s\"\n",
parent->name);

View file

@ -0,0 +1,95 @@
From bef5018abb7cf94efafdc05087b4c998891ae4ec Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 17 Jan 2022 23:39:34 +0100
Subject: [PATCH v3 10/18] ARM: dts: qcom: add saw for l2 cache and kraitcc for
ipq8064
Add saw compatible for l2 cache and kraitcc node for ipq8064 dtsi.
Also declare clock-output-names for acc0 and acc1 and qsb fixed clock
for the secondary mux.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Tested-by: Jonathan McDowell <noodles@earth.li>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 34 +++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -301,6 +301,12 @@
};
clocks {
+ qsb: qsb {
+ compatible = "fixed-clock";
+ clock-frequency = <225000000>;
+ #clock-cells = <0>;
+ };
+
cxo_board: cxo_board {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -490,6 +490,17 @@
clocks = <&gcc PLL8_VOTE>, <&pxo_board>;
clock-names = "pll8_vote", "pxo";
clock-output-names = "acpu_l2_aux";
+ #clock-cells = <0>;
+ };
+
+ kraitcc: clock-controller {
+ compatible = "qcom,krait-cc-v1";
+ clocks = <&gcc PLL9>, <&gcc PLL10>, <&gcc PLL12>,
+ <&acc0>, <&acc1>, <&l2cc>, <&qsb>, <&pxo_board>;
+ clock-names = "hfpll0", "hfpll1", "hfpll_l2",
+ "acpu0_aux", "acpu1_aux", "acpu_l2_aux",
+ "qsb", "pxo";
+ #clock-cells = <1>;
};
acc0: clock-controller@2088000 {
@@ -503,17 +509,25 @@
acc0: clock-controller@2088000 {
compatible = "qcom,kpss-acc-v1";
reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
+ clock-output-names = "acpu0_aux";
+ clocks = <&gcc PLL8_VOTE>, <&pxo_board>;
+ clock-names = "pll8_vote", "pxo";
+ #clock-cells = <0>;
};
saw0: regulator@2089000 {
- compatible = "qcom,saw2";
+ compatible = "qcom,saw2", "qcom,apq8064-saw2-v1.1-cpu", "syscon";
reg = <0x02089000 0x1000>, <0x02009000 0x1000>;
regulator;
};
acc1: clock-controller@2098000 {
compatible = "qcom,kpss-acc-v1";
reg = <0x02098000 0x1000>, <0x02008000 0x1000>;
+ clock-output-names = "acpu1_aux";
+ clocks = <&gcc PLL8_VOTE>, <&pxo_board>;
+ clock-names = "pll8_vote", "pxo";
+ #clock-cells = <0>;
};
saw1: regulator@2099000 {
@@ -531,11 +545,17 @@
};
saw1: regulator@2099000 {
- compatible = "qcom,saw2";
+ compatible = "qcom,saw2", "qcom,apq8064-saw2-v1.1-cpu", "syscon";
reg = <0x02099000 0x1000>, <0x02009000 0x1000>;
regulator;
};
+ saw_l2: regulator@02012000 {
+ compatible = "qcom,saw2", "syscon";
+ reg = <0x02012000 0x1000>;
+ regulator;
+ };
+
nss_common: syscon@03000000 {
compatible = "syscon";
reg = <0x03000000 0x0000FFFF>;

View file

@ -0,0 +1,268 @@
From 076ebb6e1799c4c7a1d2e07510d88b9e9b57b551 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Tue, 18 Jan 2022 00:03:47 +0100
Subject: [PATCH v3 13/18] ARM: dts: qcom: add opp table for cpu and l2 for
ipq8064
Add opp table for cpu and l2 cache. While the current cpufreq is
the generic one that doesn't scale the L2 cache, we add the l2
cache opp anyway for the sake of completeness. This will be handy in the
future when a dedicated cpufreq driver is introduced for krait cores
that will correctly scale l2 cache with the core freq.
Opp-level is set based on the logic of
0: idle level
1: normal level
2: turbo level
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Tested-by: Jonathan McDowell <noodles@earth.li>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 99 +++++++++++++++++++++++++++++
1 file changed, 99 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -48,6 +48,105 @@
};
};
+ opp_table_l2: opp_table_l2 {
+ compatible = "operating-points-v2";
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <100000>;
+ opp-level = <0>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <1100000>;
+ clock-latency-ns = <100000>;
+ opp-level = <1>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <1150000>;
+ clock-latency-ns = <100000>;
+ opp-level = <2>;
+ };
+ };
+
+ opp_table0: opp_table0 {
+ compatible = "operating-points-v2-kryo-cpu";
+ nvmem-cells = <&speedbin_efuse>;
+
+ /*
+ * Voltage thresholds are <target min max>
+ */
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1000000 950000 1050000>;
+ opp-microvolt-speed0-pvs1-v0 = <925000 878750 971250>;
+ opp-microvolt-speed0-pvs2-v0 = <875000 831250 918750>;
+ opp-microvolt-speed0-pvs3-v0 = <800000 760000 840000>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <0>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1050000 997500 1102500>;
+ opp-microvolt-speed0-pvs1-v0 = <975000 926250 1023750>;
+ opp-microvolt-speed0-pvs2-v0 = <925000 878750 971250>;
+ opp-microvolt-speed0-pvs3-v0 = <850000 807500 892500>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <1>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1100000 1045000 1155000>;
+ opp-microvolt-speed0-pvs1-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs2-v0 = <995000 945250 1044750>;
+ opp-microvolt-speed0-pvs3-v0 = <900000 855000 945000>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <1>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1150000 1092500 1207500>;
+ opp-microvolt-speed0-pvs1-v0 = <1075000 1021250 1128750>;
+ opp-microvolt-speed0-pvs2-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs3-v0 = <950000 902500 997500>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <1>;
+ };
+
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1200000 1140000 1260000>;
+ opp-microvolt-speed0-pvs1-v0 = <1125000 1068750 1181250>;
+ opp-microvolt-speed0-pvs2-v0 = <1075000 1021250 1128750>;
+ opp-microvolt-speed0-pvs3-v0 = <1000000 950000 1050000>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <2>;
+ };
+
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1250000 1187500 1312500>;
+ opp-microvolt-speed0-pvs1-v0 = <1175000 1116250 1233750>;
+ opp-microvolt-speed0-pvs2-v0 = <1125000 1068750 1181250>;
+ opp-microvolt-speed0-pvs3-v0 = <1050000 997500 1102500>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <2>;
+ };
+ };
+
thermal-zones {
tsens_tz_sensor0 {
polling-delay-passive = <0>;
--- a/arch/arm/boot/dts/qcom-ipq8065.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8065.dtsi
@@ -6,3 +6,92 @@
model = "Qualcomm Technologies, Inc. IPQ8065";
compatible = "qcom,ipq8065", "qcom,ipq8064";
};
+
+&opp_table_l2 {
+ /delete-node/opp-1200000000;
+
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-microvolt = <1150000>;
+ clock-latency-ns = <100000>;
+ opp-level = <2>;
+ };
+};
+
+&opp_table0 {
+ /*
+ * On ipq8065 1.2 ghz freq is not present
+ * Remove it to make cpufreq work and not
+ * complain for missing definition
+ */
+
+ /delete-node/opp-1200000000;
+
+ /*
+ * Voltage thresholds are <target min max>
+ */
+ opp-384000000 {
+ opp-microvolt-speed0-pvs0-v0 = <975000 926250 1023750>;
+ opp-microvolt-speed0-pvs1-v0 = <950000 902500 997500>;
+ opp-microvolt-speed0-pvs2-v0 = <925000 878750 971250>;
+ opp-microvolt-speed0-pvs3-v0 = <900000 855000 945000>;
+ opp-microvolt-speed0-pvs4-v0 = <875000 831250 918750>;
+ opp-microvolt-speed0-pvs5-v0 = <825000 783750 866250>;
+ opp-microvolt-speed0-pvs6-v0 = <775000 736250 813750>;
+ };
+
+ opp-600000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1000000 950000 1050000>;
+ opp-microvolt-speed0-pvs1-v0 = <975000 926250 1023750>;
+ opp-microvolt-speed0-pvs2-v0 = <950000 902500 997500>;
+ opp-microvolt-speed0-pvs3-v0 = <925000 878750 971250>;
+ opp-microvolt-speed0-pvs4-v0 = <900000 855000 945000>;
+ opp-microvolt-speed0-pvs5-v0 = <850000 807500 892500>;
+ opp-microvolt-speed0-pvs6-v0 = <800000 760000 840000>;
+ };
+
+ opp-800000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1050000 997500 1102500>;
+ opp-microvolt-speed0-pvs1-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs2-v0 = <1000000 950000 1050000>;
+ opp-microvolt-speed0-pvs3-v0 = <975000 926250 1023750>;
+ opp-microvolt-speed0-pvs4-v0 = <950000 902500 997500>;
+ opp-microvolt-speed0-pvs5-v0 = <900000 855000 945000>;
+ opp-microvolt-speed0-pvs6-v0 = <850000 807500 892500>;
+ };
+
+ opp-1000000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1100000 1045000 1155000>;
+ opp-microvolt-speed0-pvs1-v0 = <1075000 1021250 1128750>;
+ opp-microvolt-speed0-pvs2-v0 = <1050000 997500 1102500>;
+ opp-microvolt-speed0-pvs3-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs4-v0 = <1000000 950000 1050000>;
+ opp-microvolt-speed0-pvs5-v0 = <950000 902500 997500>;
+ opp-microvolt-speed0-pvs6-v0 = <900000 855000 945000>;
+ };
+
+ opp-1400000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1175000 1116250 1233750>;
+ opp-microvolt-speed0-pvs1-v0 = <1150000 1092500 1207500>;
+ opp-microvolt-speed0-pvs2-v0 = <1125000 1068750 1181250>;
+ opp-microvolt-speed0-pvs3-v0 = <1100000 1045000 1155000>;
+ opp-microvolt-speed0-pvs4-v0 = <1075000 1021250 1128750>;
+ opp-microvolt-speed0-pvs5-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs6-v0 = <975000 926250 1023750>;
+ opp-level = <1>;
+ };
+
+ opp-1725000000 {
+ opp-hz = /bits/ 64 <1725000000>;
+ opp-microvolt-speed0-pvs0-v0 = <1262500 1199375 1325625>;
+ opp-microvolt-speed0-pvs1-v0 = <1225000 1163750 1286250>;
+ opp-microvolt-speed0-pvs2-v0 = <1200000 1140000 1260000>;
+ opp-microvolt-speed0-pvs3-v0 = <1175000 1116250 1233750>;
+ opp-microvolt-speed0-pvs4-v0 = <1150000 1092500 1207500>;
+ opp-microvolt-speed0-pvs5-v0 = <1100000 1045000 1155000>;
+ opp-microvolt-speed0-pvs6-v0 = <1050000 997500 1102500>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <100000>;
+ opp-level = <2>;
+ };
+};
--- a/arch/arm/boot/dts/qcom-ipq8062.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8062.dtsi
@@ -6,3 +6,39 @@
model = "Qualcomm Technologies, Inc. IPQ8062";
compatible = "qcom,ipq8062", "qcom,ipq8064";
};
+
+&opp_table0 {
+ /delete-node/opp-1200000000;
+ /delete-node/opp-1400000000;
+
+ /*
+ * Voltage thresholds are <target min max>
+ */
+ opp-384000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1000000 950000 1050000>;
+ opp-microvolt-speed0-pvs1-v0 = < 925000 878750 971250>;
+ opp-microvolt-speed0-pvs2-v0 = < 875000 831250 918750>;
+ opp-microvolt-speed0-pvs3-v0 = < 800000 760000 840000>;
+ };
+
+ opp-600000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1050000 997500 1102500>;
+ opp-microvolt-speed0-pvs1-v0 = < 975000 926250 1023750>;
+ opp-microvolt-speed0-pvs2-v0 = < 925000 878750 971250>;
+ opp-microvolt-speed0-pvs3-v0 = < 850000 807500 892500>;
+ };
+
+ opp-800000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1100000 1045000 1155000>;
+ opp-microvolt-speed0-pvs1-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs2-v0 = < 995000 945250 1044750>;
+ opp-microvolt-speed0-pvs3-v0 = < 900000 855000 945000>;
+ };
+
+ opp-1000000000 {
+ opp-microvolt-speed0-pvs0-v0 = <1150000 1092500 1207500>;
+ opp-microvolt-speed0-pvs1-v0 = <1075000 1021250 1128750>;
+ opp-microvolt-speed0-pvs2-v0 = <1025000 973750 1076250>;
+ opp-microvolt-speed0-pvs3-v0 = < 950000 902500 997500>;
+ };
+};

View file

@ -0,0 +1,153 @@
From 211fc0c0a63c99b68663a27182e643316c2d8cbe Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Tue, 18 Jan 2022 00:07:57 +0100
Subject: [PATCH v3 15/18] ARM: dts: qcom: add multiple missing binding for cpu
and l2 for ipq8064
Add multiple binding for cpu node, l2 node and add idle-states
definition for ipq8064 dtsi.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Tested-by: Jonathan McDowell <noodles@earth.li>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 36 +++++++++++++++++++++++++++++
1 file changed, 36 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -30,6 +30,15 @@
next-level-cache = <&L2>;
qcom,acc = <&acc0>;
qcom,saw = <&saw0>;
+ clocks = <&kraitcc 0>, <&kraitcc 4>;
+ clock-names = "cpu", "l2";
+ clock-latency = <100000>;
+ operating-points-v2 = <&opp_table0>;
+ voltage-tolerance = <5>;
+ cooling-min-state = <0>;
+ cooling-max-state = <10>;
+ #cooling-cells = <2>;
+ cpu-idle-states = <&CPU_SPC>;
};
cpu1: cpu@1 {
@@ -40,11 +49,35 @@
next-level-cache = <&L2>;
qcom,acc = <&acc1>;
qcom,saw = <&saw1>;
+ clocks = <&kraitcc 1>, <&kraitcc 4>;
+ clock-names = "cpu", "l2";
+ clock-latency = <100000>;
+ operating-points-v2 = <&opp_table0>;
+ voltage-tolerance = <5>;
+ cooling-min-state = <0>;
+ cooling-max-state = <10>;
+ #cooling-cells = <2>;
+ cpu-idle-states = <&CPU_SPC>;
+ };
+
+ idle-states {
+ CPU_SPC: spc {
+ compatible = "qcom,idle-state-spc";
+ status = "disabled";
+ entry-latency-us = <400>;
+ exit-latency-us = <900>;
+ min-residency-us = <3000>;
+ };
};
L2: l2-cache {
compatible = "cache";
cache-level = <2>;
+ qcom,saw = <&saw_l2>;
+
+ clocks = <&kraitcc 4>;
+ clock-names = "l2";
+ operating-points-v2 = <&opp_table_l2>;
};
};
--- a/arch/arm/boot/dts/qcom-ipq8064-smb208.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064-smb208.dtsi
@@ -2,6 +2,18 @@
#include "qcom-ipq8064.dtsi"
+&cpu0 {
+ cpu-supply = <&smb208_s2a>;
+};
+
+&cpu1 {
+ cpu-supply = <&smb208_s2b>;
+};
+
+&L2 {
+ l2-supply = <&smb208_s1a>;
+};
+
&rpm {
smb208_regulators: regulators {
compatible = "qcom,rpm-smb208-regulators";
--- a/arch/arm/boot/dts/qcom-ipq8064-v2.0-smb208.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064-v2.0-smb208.dtsi
@@ -2,6 +2,18 @@
#include "qcom-ipq8064-v2.0.dtsi"
+&cpu0 {
+ cpu-supply = <&smb208_s2a>;
+};
+
+&cpu1 {
+ cpu-supply = <&smb208_s2b>;
+};
+
+&L2 {
+ l2-supply = <&smb208_s1a>;
+};
+
&rpm {
smb208_regulators: regulators {
compatible = "qcom,rpm-smb208-regulators";
--- a/arch/arm/boot/dts/qcom-ipq8062-smb208.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8062-smb208.dtsi
@@ -2,6 +2,18 @@
#include "qcom-ipq8062.dtsi"
+&cpu0 {
+ cpu-supply = <&smb208_s2a>;
+};
+
+&cpu1 {
+ cpu-supply = <&smb208_s2b>;
+};
+
+&L2 {
+ l2-supply = <&smb208_s1a>;
+};
+
&rpm {
smb208_regulators: regulators {
compatible = "qcom,rpm-smb208-regulators";
--- a/arch/arm/boot/dts/qcom-ipq8065-smb208.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8065-smb208.dtsi
@@ -2,6 +2,18 @@
#include "qcom-ipq8065.dtsi"
+&cpu0 {
+ cpu-supply = <&smb208_s2a>;
+};
+
+&cpu1 {
+ cpu-supply = <&smb208_s2b>;
+};
+
+&L2 {
+ l2-supply = <&smb208_s1a>;
+};
+
&rpm {
smb208_regulators: regulators {
compatible = "qcom,rpm-smb208-regulators";

View file

@ -0,0 +1,29 @@
From 6c94e0184e56f9e9f1f5d5f54b20758433e498d2 Mon Sep 17 00:00:00 2001
From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
Date: Wed, 15 Jun 2022 16:47:09 +0200
Subject: [PATCH 1/2] ARM: dts: qcom: fix wrong nad_pins definition for ipq806x
Fix wrong nand_pings definition for bias-disable pins.
Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -559,12 +559,9 @@
};
nand_pins: nand_pins {
- mux {
+ disable {
pins = "gpio34", "gpio35", "gpio36",
- "gpio37", "gpio38", "gpio39",
- "gpio40", "gpio41", "gpio42",
- "gpio43", "gpio44", "gpio45",
- "gpio46", "gpio47";
+ "gpio37", "gpio38";
function = "nand";
drive-strength = <10>;
bias-disable;

View file

@ -0,0 +1,188 @@
From 504188183408fac0f61b59f5ed8ea1773fe43669 Mon Sep 17 00:00:00 2001
From: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
Date: Wed, 15 Jun 2022 16:59:30 +0200
Subject: [PATCH 2/2] ARM: dts: qcom: add MDIO dedicated controller node for
ipq806x
Add MDIO dedicated controller attached to gmac0 and fix rb3011 dts to
correctly use the new tag.
Signed-off-by: Christian 'Ansuel' Marangi <ansuelsmth@gmail.com>
---
arch/arm/boot/dts/qcom-ipq8064-rb3011.dts | 134 +++++++++++-----------
arch/arm/boot/dts/qcom-ipq8064.dtsi | 14 +++
2 files changed, 81 insertions(+), 67 deletions(-)
--- a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
+++ b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
@@ -24,73 +24,6 @@
device_type = "memory";
};
- mdio0: mdio-0 {
- status = "okay";
- compatible = "virtual,mdio-gpio";
- gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>,
- <&qcom_pinmux 0 GPIO_ACTIVE_HIGH>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- pinctrl-0 = <&mdio0_pins>;
- pinctrl-names = "default";
-
- switch0: switch@10 {
- compatible = "qca,qca8337";
- #address-cells = <1>;
- #size-cells = <0>;
-
- dsa,member = <0 0>;
-
- pinctrl-0 = <&sw0_reset_pin>;
- pinctrl-names = "default";
-
- reset-gpios = <&qcom_pinmux 16 GPIO_ACTIVE_LOW>;
- reg = <0x10>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- switch0cpu: port@0 {
- reg = <0>;
- label = "cpu";
- ethernet = <&gmac0>;
- phy-mode = "rgmii-id";
- fixed-link {
- speed = <1000>;
- full-duplex;
- };
- };
-
- port@1 {
- reg = <1>;
- label = "sw1";
- };
-
- port@2 {
- reg = <2>;
- label = "sw2";
- };
-
- port@3 {
- reg = <3>;
- label = "sw3";
- };
-
- port@4 {
- reg = <4>;
- label = "sw4";
- };
-
- port@5 {
- reg = <5>;
- label = "sw5";
- };
- };
- };
- };
-
mdio1: mdio-1 {
status = "okay";
compatible = "virtual,mdio-gpio";
@@ -220,6 +153,73 @@
status = "okay";
};
+&mdio0 {
+ status = "okay";
+ compatible = "virtual,mdio-gpio";
+ gpios = <&qcom_pinmux 1 GPIO_ACTIVE_HIGH>,
+ <&qcom_pinmux 0 GPIO_ACTIVE_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pinctrl-0 = <&mdio0_pins>;
+ pinctrl-names = "default";
+
+ switch0: switch@10 {
+ compatible = "qca,qca8337";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dsa,member = <0 0>;
+
+ pinctrl-0 = <&sw0_reset_pin>;
+ pinctrl-names = "default";
+
+ reset-gpios = <&qcom_pinmux 16 GPIO_ACTIVE_LOW>;
+ reg = <0x10>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ switch0cpu: port@0 {
+ reg = <0>;
+ label = "cpu";
+ ethernet = <&gmac0>;
+ phy-mode = "rgmii-id";
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "sw1";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "sw2";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "sw3";
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "sw4";
+ };
+
+ port@5 {
+ reg = <5>;
+ label = "sw5";
+ };
+ };
+ };
+};
+
&gmac0 {
status = "okay";
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -1446,6 +1446,20 @@
};
};
+ mdio0: mdio@37000000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "qcom,ipq8064-mdio", "syscon";
+ reg = <0x37000000 0x200000>;
+ resets = <&gcc GMAC_CORE1_RESET>;
+ reset-names = "stmmaceth";
+ clocks = <&gcc GMAC_CORE1_CLK>;
+ clock-names = "stmmaceth";
+
+ status = "disabled";
+ };
+
vsdcc_fixed: vsdcc-regulator {
compatible = "regulator-fixed";
regulator-name = "SDCC Power";

View file

@ -0,0 +1,41 @@
From 8f32d48a309246a80bdca505968085a484d54408 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 19 Apr 2021 03:01:53 +0200
Subject: [thermal-next PATCH v2 1/2] thermal: qcom: tsens: init debugfs only with
successful probe
calibrate and tsens_register can fail or PROBE_DEFER. This will cause a
double or a wrong init of the debugfs information. Init debugfs only
with successful probe fixing warning about directory already present.
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Acked-by: Thara Gopinath <thara.gopinath@linaro.org>
---
drivers/thermal/qcom/tsens.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -917,8 +917,6 @@ int __init init_common(struct tsens_priv
if (tsens_version(priv) >= VER_0_1)
tsens_enable_irq(priv);
- tsens_debug_init(op);
-
err_put_device:
put_device(&op->dev);
return ret;
@@ -1157,7 +1155,12 @@ static int tsens_probe(struct platform_d
}
}
- return tsens_register(priv);
+ ret = tsens_register(priv);
+
+ if (!ret)
+ tsens_debug_init(pdev);
+
+ return ret;
}
static int tsens_remove(struct platform_device *pdev)

View file

@ -0,0 +1,54 @@
From 4204f22060f7a5d42c6ccb4d4c25a6a875571099 Mon Sep 17 00:00:00 2001
From: Ansuel Smith <ansuelsmth@gmail.com>
Date: Mon, 19 Apr 2021 03:08:37 +0200
Subject: [thermal-next PATCH v2 2/2] thermal: qcom: tsens: simplify debugfs init
function
Simplify debugfs init function.
- Add check for existing dev directory.
- Fix wrong version in dbg_version_show (with version 0.0.0, 0.1.0 was
incorrectly reported)
Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
Reviewed-by: Thara Gopinath <thara.gopinath@linaro.org>
---
drivers/thermal/qcom/tsens.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -691,7 +691,7 @@ static int dbg_version_show(struct seq_f
return ret;
seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver);
} else {
- seq_puts(s, "0.1.0\n");
+ seq_printf(s, "0.%d.0\n", priv->feat->ver_major);
}
return 0;
@@ -703,21 +703,17 @@ DEFINE_SHOW_ATTRIBUTE(dbg_sensors);
static void tsens_debug_init(struct platform_device *pdev)
{
struct tsens_priv *priv = platform_get_drvdata(pdev);
- struct dentry *root, *file;
- root = debugfs_lookup("tsens", NULL);
- if (!root)
+ priv->debug_root = debugfs_lookup("tsens", NULL);
+ if (!priv->debug_root)
priv->debug_root = debugfs_create_dir("tsens", NULL);
- else
- priv->debug_root = root;
- file = debugfs_lookup("version", priv->debug_root);
- if (!file)
+ if (!debugfs_lookup("version", priv->debug_root))
debugfs_create_file("version", 0444, priv->debug_root,
pdev, &dbg_version_fops);
/* A directory for each instance of the TSENS IP */
- priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root);
+ priv->debug = debugfs_lookup(dev_name(&pdev->dev), priv->debug_root);
debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops);
}
#else

View file

@ -0,0 +1,235 @@
From b044ae89862132a86fb511648e9c52ea3cdf8c30 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Wed, 5 Aug 2020 14:19:23 +0200
Subject: [PATCH 1/4] devfreq: qcom: Add L2 Krait Cache devfreq scaling driver
Qcom L2 Krait CPUs use the generic cpufreq-dt driver and doesn't actually
scale the Cache frequency when the CPU frequency is changed. This
devfreq driver register with the cpu notifier and scale the Cache
based on the max Freq across all core as the CPU cache is shared across
all of them. If provided this also scale the voltage of the regulator
attached to the CPU cache. The scaling logic is based on the CPU freq
and the 3 scaling interval are set by the device dts.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/devfreq/Kconfig | 11 ++
drivers/devfreq/Makefile | 1 +
drivers/devfreq/krait-cache-devfreq.c | 188 ++++++++++++++++++++++++++
3 files changed, 200 insertions(+)
create mode 100644 drivers/devfreq/krait-cache-devfreq.c
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -132,6 +132,17 @@ config ARM_RK3399_DMC_DEVFREQ
It sets the frequency for the memory controller and reads the usage counts
from hardware.
+config ARM_KRAIT_CACHE_DEVFREQ
+ tristate "Scaling support for Krait CPU Cache Devfreq"
+ depends on ARCH_QCOM || COMPILE_TEST
+ select DEVFREQ_GOV_PASSIVE
+ help
+ This adds the DEVFREQ driver for the Krait CPU L2 Cache shared by all cores.
+
+ The driver register with the cpufreq notifier and find the right frequency
+ based on the max frequency across all core and the range set in the device
+ dts. If provided this scale also the regulator attached to the l2 cache.
+
source "drivers/devfreq/event/Kconfig"
endif # PM_DEVFREQ
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_ARM_IMX_BUS_DEVFREQ) += imx
obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) += imx8m-ddrc.o
obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o
+obj-$(CONFIG_ARM_KRAIT_CACHE_DEVFREQ) += krait-cache-devfreq.o
# DEVFREQ Event Drivers
obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
--- /dev/null
+++ b/drivers/devfreq/krait-cache-devfreq.c
@@ -0,0 +1,181 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/devfreq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_opp.h>
+
+#include "governor.h"
+
+struct krait_cache_data {
+ struct clk *clk;
+ unsigned long idle_freq;
+ int token;
+};
+
+static int krait_cache_config_clk(struct device *dev, struct opp_table *opp_table,
+ struct dev_pm_opp *old_opp, struct dev_pm_opp *opp,
+ void *data, bool scaling_down)
+{
+ struct krait_cache_data *kdata;
+ unsigned long old_freq, freq;
+ unsigned long idle_freq;
+ struct clk *clk;
+ int ret;
+
+ kdata = dev_get_drvdata(dev);
+ idle_freq = kdata->idle_freq;
+ clk = kdata->clk;
+
+ old_freq = dev_pm_opp_get_freq(old_opp);
+ freq = dev_pm_opp_get_freq(opp);
+
+ /*
+ * Set to idle bin if switching from normal to high bin
+ * or vice versa. It has been notice that a bug is triggered
+ * in cache scaling when more than one bin is scaled, to fix
+ * this we first need to transition to the base rate and then
+ * to target rate
+ */
+ if (likely(freq != idle_freq && old_freq != idle_freq)) {
+ ret = clk_set_rate(clk, idle_freq);
+ if (ret)
+ return ret;
+ }
+
+ return clk_set_rate(clk, freq);
+};
+
+static int krait_cache_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ struct krait_cache_data *data = dev_get_drvdata(dev);
+
+ *freq = clk_get_rate(data->clk);
+
+ return 0;
+};
+
+static int krait_cache_target(struct device *dev, unsigned long *freq,
+ u32 flags)
+{
+ struct dev_pm_opp *opp;
+
+ opp = dev_pm_opp_find_freq_ceil(dev, freq);
+ if (unlikely(IS_ERR(opp)))
+ return PTR_ERR(opp);
+
+ dev_pm_opp_put(opp);
+
+ return dev_pm_opp_set_rate(dev, *freq);
+};
+
+static int krait_cache_get_dev_status(struct device *dev,
+ struct devfreq_dev_status *stat)
+{
+ struct krait_cache_data *data = dev_get_drvdata(dev);
+
+ stat->busy_time = 0;
+ stat->total_time = 0;
+ stat->current_frequency = clk_get_rate(data->clk);
+
+ return 0;
+};
+
+static struct devfreq_dev_profile krait_cache_devfreq_profile = {
+ .target = krait_cache_target,
+ .get_dev_status = krait_cache_get_dev_status,
+ .get_cur_freq = krait_cache_get_cur_freq
+};
+
+static struct devfreq_passive_data devfreq_gov_data = {
+ .parent_type = CPUFREQ_PARENT_DEV,
+};
+
+static int krait_cache_probe(struct platform_device *pdev)
+{
+ struct dev_pm_opp_config config = { };
+ struct device *dev = &pdev->dev;
+ struct krait_cache_data *data;
+ struct devfreq *devfreq;
+ struct dev_pm_opp *opp;
+ struct clk *clk;
+ int ret, token;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ clk = devm_clk_get(dev, "l2");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ config.regulator_names = (const char *[]){ "l2", NULL };
+ config.clk_names = (const char *[]){ "l2", NULL };
+ config.config_clks = krait_cache_config_clk;
+
+ token = dev_pm_opp_set_config(dev, &config);
+ if (token < 0)
+ return token;
+
+ ret = devm_pm_opp_of_add_table(dev);
+ if (ret)
+ goto free_opp;
+
+ opp = dev_pm_opp_find_freq_ceil(dev, &data->idle_freq);
+ if (IS_ERR(opp)) {
+ ret = PTR_ERR(opp);
+ goto free_opp;
+ }
+ dev_pm_opp_put(opp);
+
+ data->token = token;
+ data->clk = clk;
+ dev_set_drvdata(dev, data);
+ devfreq = devm_devfreq_add_device(dev, &krait_cache_devfreq_profile,
+ DEVFREQ_GOV_PASSIVE, &devfreq_gov_data);
+ if (IS_ERR(devfreq)) {
+ ret = PTR_ERR(devfreq);
+ goto free_opp;
+ }
+
+ return 0;
+
+free_opp:
+ dev_pm_opp_clear_config(token);
+ return ret;
+};
+
+static int krait_cache_remove(struct platform_device *pdev)
+{
+ struct krait_cache_data *data = dev_get_drvdata(&pdev->dev);
+
+ dev_pm_opp_clear_config(data->token);
+
+ return 0;
+};
+
+static const struct of_device_id krait_cache_match_table[] = {
+ { .compatible = "qcom,krait-cache" },
+ {}
+};
+
+static struct platform_driver krait_cache_driver = {
+ .probe = krait_cache_probe,
+ .remove = krait_cache_remove,
+ .driver = {
+ .name = "krait-cache-scaling",
+ .of_match_table = krait_cache_match_table,
+ },
+};
+module_platform_driver(krait_cache_driver);
+
+MODULE_DESCRIPTION("Krait CPU Cache Scaling driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,50 @@
From ef124ad0ff8abfbf4ebe3fe6d7dcef4541dec13a Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 16 Jun 2022 18:39:21 +0200
Subject: [PATCH] ARM: dts: qcom: add krait-cache compatible for ipq806x dtsi
Add qcom,krait-cache compatible to enable cache devfreq driver for
ipq806x SoC and move the L2 node to the soc node to make the devfreq
driver correctly probe.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -69,16 +69,6 @@
min-residency-us = <3000>;
};
};
-
- L2: l2-cache {
- compatible = "cache";
- cache-level = <2>;
- qcom,saw = <&saw_l2>;
-
- clocks = <&kraitcc 4>;
- clock-names = "l2";
- operating-points-v2 = <&opp_table_l2>;
- };
};
opp_table_l2: opp_table_l2 {
@@ -470,6 +460,16 @@
ranges;
compatible = "simple-bus";
+ L2: l2-cache {
+ compatible = "cache", "qcom,krait-cache";
+ cache-level = <2>;
+ qcom,saw = <&saw_l2>;
+
+ clocks = <&kraitcc 4>;
+ clock-names = "l2";
+ operating-points-v2 = <&opp_table_l2>;
+ };
+
lpass@28100000 {
compatible = "qcom,lpass-cpu";
status = "disabled";

View file

@ -0,0 +1,203 @@
From 13f075999935bb696dbab63243923179f06fa05e Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 16 Jun 2022 19:56:08 +0200
Subject: [PATCH 3/4] devfreq: add ipq806x fabric scaling driver
Add ipq806x fabric scaling driver using the devfreq passive governor.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/devfreq/Kconfig | 11 ++
drivers/devfreq/Makefile | 1 +
drivers/devfreq/ipq806x-fab-devfreq.c | 155 ++++++++++++++++++++++++++
3 files changed, 167 insertions(+)
create mode 100644 drivers/devfreq/ipq806x-fab-devfreq.c
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -143,6 +143,17 @@ config ARM_KRAIT_CACHE_DEVFREQ
based on the max frequency across all core and the range set in the device
dts. If provided this scale also the regulator attached to the l2 cache.
+config ARM_IPQ806X_FAB_DEVFREQ
+ tristate "Scaling support for ipq806x Soc Fabric"
+ depends on ARCH_QCOM || COMPILE_TEST
+ select DEVFREQ_GOV_PASSIVE
+ help
+ This adds the DEVFREQ driver for the ipq806x Soc Fabric.
+
+ The driver register with the cpufreq notifier and find the right frequency
+ based on the max frequency across all core and the range set in the device
+ dts.
+
source "drivers/devfreq/event/Kconfig"
endif # PM_DEVFREQ
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_ARM_IMX8M_DDRC_DEVFREQ) +=
obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra30-devfreq.o
obj-$(CONFIG_ARM_KRAIT_CACHE_DEVFREQ) += krait-cache-devfreq.o
+obj-$(CONFIG_ARM_IPQ806X_FAB_DEVFREQ) += ipq806x-fab-devfreq.o
# DEVFREQ Event Drivers
obj-$(CONFIG_PM_DEVFREQ_EVENT) += event/
--- /dev/null
+++ b/drivers/devfreq/ipq806x-fab-devfreq.c
@@ -0,0 +1,155 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/cpufreq.h>
+#include <linux/devfreq.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/pm_opp.h>
+
+#include "governor.h"
+
+struct ipq806x_fab_data {
+ struct clk *fab_clk;
+ struct clk *ddr_clk;
+};
+
+static int ipq806x_fab_get_cur_freq(struct device *dev, unsigned long *freq)
+{
+ struct ipq806x_fab_data *data = dev_get_drvdata(dev);
+
+ *freq = clk_get_rate(data->fab_clk);
+
+ return 0;
+};
+
+static int ipq806x_fab_target(struct device *dev, unsigned long *freq,
+ u32 flags)
+{
+ struct ipq806x_fab_data *data = dev_get_drvdata(dev);
+ struct dev_pm_opp *opp;
+ int ret;
+
+ opp = dev_pm_opp_find_freq_ceil(dev, freq);
+ if (unlikely(IS_ERR(opp)))
+ return PTR_ERR(opp);
+
+ dev_pm_opp_put(opp);
+
+ ret = clk_set_rate(data->fab_clk, *freq);
+ if (ret)
+ return ret;
+
+ return clk_set_rate(data->ddr_clk, *freq);
+};
+
+static int ipq806x_fab_get_dev_status(struct device *dev,
+ struct devfreq_dev_status *stat)
+{
+ struct ipq806x_fab_data *data = dev_get_drvdata(dev);
+
+ stat->busy_time = 0;
+ stat->total_time = 0;
+ stat->current_frequency = clk_get_rate(data->fab_clk);
+
+ return 0;
+};
+
+static struct devfreq_dev_profile ipq806x_fab_devfreq_profile = {
+ .target = ipq806x_fab_target,
+ .get_dev_status = ipq806x_fab_get_dev_status,
+ .get_cur_freq = ipq806x_fab_get_cur_freq
+};
+
+static struct devfreq_passive_data devfreq_gov_data = {
+ .parent_type = CPUFREQ_PARENT_DEV,
+};
+
+static int ipq806x_fab_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ipq806x_fab_data *data;
+ struct devfreq *devfreq;
+ struct clk *clk;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ clk = devm_clk_get(dev, "apps-fab-clk");
+ if (IS_ERR(clk)) {
+ dev_err_probe(dev, PTR_ERR(clk), "failed to get apps fab clk\n");
+ return PTR_ERR(clk);
+ }
+
+ clk_prepare_enable(clk);
+ data->fab_clk = clk;
+
+ clk = devm_clk_get(dev, "ddr-fab-clk");
+ if (IS_ERR(clk)) {
+ dev_err_probe(dev, PTR_ERR(clk), "failed to get ddr fab clk\n");
+ goto err_ddr;
+ }
+
+ clk_prepare_enable(clk);
+ data->ddr_clk = clk;
+
+ ret = dev_pm_opp_of_add_table(dev);
+ if (ret) {
+ dev_err(dev, "failed to parse fab freq thresholds\n");
+ return ret;
+ }
+
+ dev_set_drvdata(dev, data);
+
+ devfreq = devm_devfreq_add_device(&pdev->dev, &ipq806x_fab_devfreq_profile,
+ DEVFREQ_GOV_PASSIVE, &devfreq_gov_data);
+ if (IS_ERR(devfreq))
+ dev_pm_opp_remove_table(dev);
+
+ return PTR_ERR_OR_ZERO(devfreq);
+
+err_ddr:
+ clk_unprepare(data->fab_clk);
+ clk_put(data->fab_clk);
+ return PTR_ERR(clk);
+};
+
+static int ipq806x_fab_remove(struct platform_device *pdev)
+{
+ struct ipq806x_fab_data *data = dev_get_drvdata(&pdev->dev);
+
+ clk_unprepare(data->fab_clk);
+ clk_put(data->fab_clk);
+
+ clk_unprepare(data->ddr_clk);
+ clk_put(data->ddr_clk);
+
+ dev_pm_opp_remove_table(&pdev->dev);
+
+ return 0;
+};
+
+static const struct of_device_id ipq806x_fab_match_table[] = {
+ { .compatible = "qcom,fab-scaling" },
+ {}
+};
+
+static struct platform_driver ipq806x_fab_driver = {
+ .probe = ipq806x_fab_probe,
+ .remove = ipq806x_fab_remove,
+ .driver = {
+ .name = "ipq806x-fab-scaling",
+ .of_match_table = ipq806x_fab_match_table,
+ },
+};
+module_platform_driver(ipq806x_fab_driver);
+
+MODULE_DESCRIPTION("ipq806x Fab Scaling driver");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_LICENSE("GPL v2");

View file

@ -0,0 +1,48 @@
From c3573f0907dadb0a6e9933aae2a46a489abcbd48 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 16 Jun 2022 20:03:05 +0200
Subject: [PATCH 4/4] ARM: dts: qcom: add fab scaling node for ipq806x
Add fabric scaling node for ipq806x to correctly scale apps and ddr
fabric clk.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -170,6 +170,18 @@
};
};
+ opp_table_fab: opp_table_fab {
+ compatible = "operating-points-v2";
+
+ opp-533000000 {
+ opp-hz = /bits/ 64 <533000000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ };
+ };
+
thermal-zones {
tsens_tz_sensor0 {
polling-delay-passive = <0>;
@@ -470,6 +482,13 @@
operating-points-v2 = <&opp_table_l2>;
};
+ fab-scaling {
+ compatible = "qcom,fab-scaling";
+ clocks = <&rpmcc RPM_APPS_FABRIC_A_CLK>, <&rpmcc RPM_EBI1_A_CLK>;
+ clock-names = "apps-fab-clk", "ddr-fab-clk";
+ operating-points-v2 = <&opp_table_fab>;
+ };
+
lpass@28100000 {
compatible = "qcom,lpass-cpu";
status = "disabled";

View file

@ -0,0 +1,31 @@
From ac84ac819a2e8fd3d87122b452c502a386c54437 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Tue, 5 Jul 2022 18:30:18 +0200
Subject: [PATCH v2 4/4] clk: qcom: gcc-ipq806x: remove cc_register_board for
pxo and cxo
Now that these clock are defined as fixed clk in dts, we can drop the
register_board_clk for cxo_board and pxo_board in gcc_ipq806x_probe.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/gcc-ipq806x.c | 8 --------
1 file changed, 8 deletions(-)
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -3384,14 +3384,6 @@ static int gcc_ipq806x_probe(struct plat
struct regmap *regmap;
int ret;
- ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 25000000);
- if (ret)
- return ret;
-
- ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 25000000);
- if (ret)
- return ret;
-
if (of_machine_is_compatible("qcom,ipq8065")) {
ubi32_core1_src_clk.freq_tbl = clk_tbl_nss_ipq8065;
ubi32_core2_src_clk.freq_tbl = clk_tbl_nss_ipq8065;

View file

@ -0,0 +1,63 @@
From 09930efb4f4fb81019ca33bf64827ce258eca66f Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 01:58:12 +0200
Subject: [PATCH 1/9] clk: qcom: kpss-xcc: register it as clk provider
krait-cc use this driver for the secondary mux. Register it as a clk
provider to correctly use this clk in other drivers.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/kpss-xcc.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c
index b1b370274ec4..97358c98c6c9 100644
--- a/drivers/clk/qcom/kpss-xcc.c
+++ b/drivers/clk/qcom/kpss-xcc.c
@@ -31,12 +31,13 @@ MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
static int kpss_xcc_driver_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
const struct of_device_id *id;
void __iomem *base;
struct clk_hw *hw;
const char *name;
- id = of_match_device(kpss_xcc_match_table, &pdev->dev);
+ id = of_match_device(kpss_xcc_match_table, dev);
if (!id)
return -ENODEV;
@@ -45,7 +46,7 @@ static int kpss_xcc_driver_probe(struct platform_device *pdev)
return PTR_ERR(base);
if (id->data) {
- if (of_property_read_string_index(pdev->dev.of_node,
+ if (of_property_read_string_index(dev->of_node,
"clock-output-names",
0, &name))
return -ENODEV;
@@ -55,12 +56,16 @@ static int kpss_xcc_driver_probe(struct platform_device *pdev)
base += 0x28;
}
- hw = devm_clk_hw_register_mux_parent_data_table(&pdev->dev, name, aux_parents,
+ hw = devm_clk_hw_register_mux_parent_data_table(dev, name, aux_parents,
ARRAY_SIZE(aux_parents), 0,
base, 0, 0x3,
0, aux_parent_map, NULL);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
- return PTR_ERR_OR_ZERO(hw);
+ of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, hw);
+
+ return 0;
}
static struct platform_driver kpss_xcc_driver = {
--
2.37.2

View file

@ -0,0 +1,269 @@
From 334c1540d5753a3c83a4cb84d935d606cb47a03b Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 17 Feb 2022 23:02:59 +0100
Subject: [PATCH 2/9] clk: qcom: krait-cc: convert to parent_data API
Modernize the krait-cc driver to parent-data API and refactor to drop
any use of clk_names. From Documentation all the required clocks should
be declared in DTS so fw_name can be correctly used to get the parents
for all the muxes. .name is also declared to save compatibility with old
implementation.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 126 +++++++++++++++++++-----------------
1 file changed, 66 insertions(+), 60 deletions(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index cfd961d5cc45..84f0048961f5 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -69,21 +69,22 @@ static int krait_notifier_register(struct device *dev, struct clk *clk,
return ret;
}
-static int
+static struct clk *
krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
{
struct krait_div2_clk *div;
+ static struct clk_parent_data p_data[1];
struct clk_init_data init = {
- .num_parents = 1,
+ .num_parents = ARRAY_SIZE(p_data),
.ops = &krait_div2_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
- const char *p_names[1];
struct clk *clk;
+ char *parent_name;
div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
if (!div)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
div->width = 2;
div->shift = 6;
@@ -93,43 +94,49 @@ krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
if (!init.name)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- init.parent_names = p_names;
- p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
- if (!p_names[0]) {
- kfree(init.name);
- return -ENOMEM;
+ init.parent_data = p_data;
+ parent_name = kasprintf(GFP_KERNEL, "hfpll%s", s);
+ if (!parent_name) {
+ clk = ERR_PTR(-ENOMEM);
+ goto err_parent_name;
}
+ p_data[0].fw_name = parent_name;
+ p_data[0].name = parent_name;
+
clk = devm_clk_register(dev, &div->hw);
- kfree(p_names[0]);
+
+ kfree(parent_name);
+err_parent_name:
kfree(init.name);
- return PTR_ERR_OR_ZERO(clk);
+ return clk;
}
-static int
+static struct clk *
krait_add_sec_mux(struct device *dev, int id, const char *s,
unsigned int offset, bool unique_aux)
{
int ret;
struct krait_mux_clk *mux;
- static const char *sec_mux_list[] = {
- "acpu_aux",
- "qsb",
+ static struct clk_parent_data sec_mux_list[2] = {
+ { .name = "qsb", .fw_name = "qsb" },
+ {},
};
struct clk_init_data init = {
- .parent_names = sec_mux_list,
+ .parent_data = sec_mux_list,
.num_parents = ARRAY_SIZE(sec_mux_list),
.ops = &krait_mux_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
struct clk *clk;
+ char *parent_name;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
mux->offset = offset;
mux->lpl = id >= 0;
@@ -149,44 +156,51 @@ krait_add_sec_mux(struct device *dev, int id, const char *s,
init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
if (!init.name)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
if (unique_aux) {
- sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
- if (!sec_mux_list[0]) {
+ parent_name = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
+ if (!parent_name) {
clk = ERR_PTR(-ENOMEM);
goto err_aux;
}
+ sec_mux_list[1].fw_name = parent_name;
+ sec_mux_list[1].name = parent_name;
+ } else {
+ sec_mux_list[1].name = "apu_aux";
}
clk = devm_clk_register(dev, &mux->hw);
+ if (IS_ERR(clk))
+ goto err_clk;
ret = krait_notifier_register(dev, clk, mux);
if (ret)
- goto unique_aux;
+ clk = ERR_PTR(ret);
-unique_aux:
+err_clk:
if (unique_aux)
- kfree(sec_mux_list[0]);
+ kfree(parent_name);
err_aux:
kfree(init.name);
- return PTR_ERR_OR_ZERO(clk);
+ return clk;
}
static struct clk *
-krait_add_pri_mux(struct device *dev, int id, const char *s,
- unsigned int offset)
+krait_add_pri_mux(struct device *dev, struct clk *hfpll_div, struct clk *sec_mux,
+ int id, const char *s, unsigned int offset)
{
int ret;
struct krait_mux_clk *mux;
- const char *p_names[3];
+ static struct clk_parent_data p_data[3];
struct clk_init_data init = {
- .parent_names = p_names,
- .num_parents = ARRAY_SIZE(p_names),
+ .parent_data = p_data,
+ .num_parents = ARRAY_SIZE(p_data),
.ops = &krait_mux_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
struct clk *clk;
+ char *hfpll_name;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux)
@@ -204,36 +218,29 @@ krait_add_pri_mux(struct device *dev, int id, const char *s,
if (!init.name)
return ERR_PTR(-ENOMEM);
- p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
- if (!p_names[0]) {
+ hfpll_name = kasprintf(GFP_KERNEL, "hfpll%s", s);
+ if (!hfpll_name) {
clk = ERR_PTR(-ENOMEM);
- goto err_p0;
+ goto err_hfpll;
}
- p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
- if (!p_names[1]) {
- clk = ERR_PTR(-ENOMEM);
- goto err_p1;
- }
+ p_data[0].fw_name = hfpll_name;
+ p_data[0].name = hfpll_name;
- p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
- if (!p_names[2]) {
- clk = ERR_PTR(-ENOMEM);
- goto err_p2;
- }
+ p_data[1].hw = __clk_get_hw(hfpll_div);
+ p_data[2].hw = __clk_get_hw(sec_mux);
clk = devm_clk_register(dev, &mux->hw);
+ if (IS_ERR(clk))
+ goto err_clk;
ret = krait_notifier_register(dev, clk, mux);
if (ret)
- goto err_p3;
-err_p3:
- kfree(p_names[2]);
-err_p2:
- kfree(p_names[1]);
-err_p1:
- kfree(p_names[0]);
-err_p0:
+ clk = ERR_PTR(ret);
+
+err_clk:
+ kfree(hfpll_name);
+err_hfpll:
kfree(init.name);
return clk;
}
@@ -241,11 +248,10 @@ krait_add_pri_mux(struct device *dev, int id, const char *s,
/* id < 0 for L2, otherwise id == physical CPU number */
static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
{
- int ret;
unsigned int offset;
void *p = NULL;
const char *s;
- struct clk *clk;
+ struct clk *hfpll_div, *sec_mux, *clk;
if (id >= 0) {
offset = 0x4501 + (0x1000 * id);
@@ -257,19 +263,19 @@ static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
s = "_l2";
}
- ret = krait_add_div(dev, id, s, offset);
- if (ret) {
- clk = ERR_PTR(ret);
+ hfpll_div = krait_add_div(dev, id, s, offset);
+ if (IS_ERR(hfpll_div)) {
+ clk = hfpll_div;
goto err;
}
- ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
- if (ret) {
- clk = ERR_PTR(ret);
+ sec_mux = krait_add_sec_mux(dev, id, s, offset, unique_aux);
+ if (IS_ERR(sec_mux)) {
+ clk = sec_mux;
goto err;
}
- clk = krait_add_pri_mux(dev, id, s, offset);
+ clk = krait_add_pri_mux(dev, hfpll_div, sec_mux, id, s, offset);
err:
kfree(p);
return clk;
--
2.37.2

View file

@ -0,0 +1,52 @@
From 666c1b745e93ccddde841d5057c33f97b29a316a Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 02:19:28 +0200
Subject: [PATCH 3/9] clk: qcom: krait-cc: handle qsb clock defined in DTS
qsb fixed clk may be defined in DTS and correctly passed in the clocks
list. Add related code to handle this and modify the logic to
dynamically read qsb clock frequency.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index 84f0048961f5..f1d64b16cac3 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -305,7 +305,7 @@ static int krait_cc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *id;
- unsigned long cur_rate, aux_rate;
+ unsigned long cur_rate, aux_rate, qsb_rate;
int cpu;
struct clk *clk;
struct clk **clks;
@@ -315,11 +315,19 @@ static int krait_cc_probe(struct platform_device *pdev)
if (!id)
return -ENODEV;
- /* Rate is 1 because 0 causes problems for __clk_mux_determine_rate */
- clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1);
+ /*
+ * Per Documentation qsb should be provided from DTS.
+ * To address old implementation, register the fixed clock anyway.
+ * Rate is 1 because 0 causes problems for __clk_mux_determine_rate
+ */
+ clk = clk_get(dev, "qsb");
+ if (IS_ERR(clk))
+ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1);
if (IS_ERR(clk))
return PTR_ERR(clk);
+ qsb_rate = clk_get_rate(clk);
+
if (!id->data) {
clk = clk_register_fixed_factor(dev, "acpu_aux",
"gpll0_vote", 0, 1, 2);
--
2.37.2

View file

@ -0,0 +1,59 @@
From fca6f185a9d9ef0892a719bc6da955b22d326ec7 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 02:24:33 +0200
Subject: [PATCH 4/9] clk: qcom: krait-cc: register REAL qsb fixed clock
With some tools it was discovered the real frequency of the qsb fixed
clock. While not 100% correct it's still better than using 1 as a dummy
frequency.
Correctly register the qsb fixed clock with the frequency of 225 MHz
instead of 1.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index f1d64b16cac3..e91275663973 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -15,6 +15,8 @@
#include "clk-krait.h"
+#define QSB_RATE 2250000000
+
static unsigned int sec_mux_map[] = {
2,
0,
@@ -322,7 +324,7 @@ static int krait_cc_probe(struct platform_device *pdev)
*/
clk = clk_get(dev, "qsb");
if (IS_ERR(clk))
- clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, 1);
+ clk = clk_register_fixed_rate(dev, "qsb", NULL, 0, QSB_RATE);
if (IS_ERR(clk))
return PTR_ERR(clk);
@@ -378,7 +380,7 @@ static int krait_cc_probe(struct platform_device *pdev)
*/
cur_rate = clk_get_rate(l2_pri_mux_clk);
aux_rate = 384000000;
- if (cur_rate == 1) {
+ if (cur_rate == qsb_rate) {
pr_info("L2 @ QSB rate. Forcing new rate.\n");
cur_rate = aux_rate;
}
@@ -389,7 +391,7 @@ static int krait_cc_probe(struct platform_device *pdev)
for_each_possible_cpu(cpu) {
clk = clks[cpu];
cur_rate = clk_get_rate(clk);
- if (cur_rate == 1) {
+ if (cur_rate == qsb_rate) {
pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
cur_rate = aux_rate;
}
--
2.37.2

View file

@ -0,0 +1,30 @@
From ff65b60fa89be06ba68e3e22702dd71700afb6a5 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 02:34:58 +0200
Subject: [PATCH 5/9] clk: qcom: krait-cc: use devm variant for clk notifier
register
Use devm variant for clk notifier register and correctly handle free
resource on driver remove.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index e91275663973..33a78b7de0bd 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -64,7 +64,7 @@ static int krait_notifier_register(struct device *dev, struct clk *clk,
int ret = 0;
mux->clk_nb.notifier_call = krait_notifier_cb;
- ret = clk_notifier_register(clk, &mux->clk_nb);
+ ret = devm_clk_notifier_register(dev, clk, &mux->clk_nb);
if (ret)
dev_err(dev, "failed to register clock notifier: %d\n", ret);
--
2.37.2

View file

@ -0,0 +1,52 @@
From a0f6d7abe7f5da1a9b435eed89acace7cde4add6 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 02:39:11 +0200
Subject: [PATCH 6/9] clk: qcom: krait-cc: fix never enabled secondary mux
While never actually used as a pure mux, the secondary mux is used as a
safe selection for the primary mux to switch while the hfpll are
reprogrammed.
The secondary muxes were never enabled and this cause the krait-clk
drivers to silently ignore any set parent request without any error.
Enable the secondary mux to actually apply the parent and apply the
requested frequency.
Fixes: bb5c4a85051e ("clk: qcom: Add Krait clock controller driver")
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index 33a78b7de0bd..b71067a49ee7 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -121,7 +121,7 @@ static struct clk *
krait_add_sec_mux(struct device *dev, int id, const char *s,
unsigned int offset, bool unique_aux)
{
- int ret;
+ int ret, cpu;
struct krait_mux_clk *mux;
static struct clk_parent_data sec_mux_list[2] = {
{ .name = "qsb", .fw_name = "qsb" },
@@ -180,6 +180,16 @@ krait_add_sec_mux(struct device *dev, int id, const char *s,
if (ret)
clk = ERR_PTR(ret);
+ /* The secondary mux MUST be enabled or clk-krait silently
+ * ignore any request.
+ * Increase refcount for every CPU if it's the L2 secondary mux.
+ */
+ if (id < 0)
+ for_each_possible_cpu(cpu)
+ clk_prepare_enable(clk);
+ else
+ clk_prepare_enable(clk);
+
err_clk:
if (unique_aux)
kfree(parent_name);
--
2.37.2

View file

@ -0,0 +1,49 @@
From 2399d181557d94ae9a2686926cd25768f132e4b4 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 18 Mar 2022 16:12:14 +0100
Subject: [PATCH 7/9] clk: qcom: krait-cc: drop pr_info and use dev_info
Replace pr_info() with dev_info() to provide better diagnostics.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index b71067a49ee7..e4fb3ff2b5b5 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -391,25 +391,25 @@ static int krait_cc_probe(struct platform_device *pdev)
cur_rate = clk_get_rate(l2_pri_mux_clk);
aux_rate = 384000000;
if (cur_rate == qsb_rate) {
- pr_info("L2 @ QSB rate. Forcing new rate.\n");
+ dev_info(dev, "L2 @ QSB rate. Forcing new rate.\n");
cur_rate = aux_rate;
}
clk_set_rate(l2_pri_mux_clk, aux_rate);
clk_set_rate(l2_pri_mux_clk, 2);
clk_set_rate(l2_pri_mux_clk, cur_rate);
- pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
+ dev_info(dev, "L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
for_each_possible_cpu(cpu) {
clk = clks[cpu];
cur_rate = clk_get_rate(clk);
if (cur_rate == qsb_rate) {
- pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
+ dev_info(dev, "CPU%d @ QSB rate. Forcing new rate.\n", cpu);
cur_rate = aux_rate;
}
clk_set_rate(clk, aux_rate);
clk_set_rate(clk, 2);
clk_set_rate(clk, cur_rate);
- pr_info("CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
+ dev_info(dev, "CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
}
of_clk_add_provider(dev->of_node, krait_of_get, clks);
--
2.37.2

View file

@ -0,0 +1,75 @@
From b6655ca513b3f1b40417287ab7f706409455fe48 Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 02:56:47 +0200
Subject: [PATCH 8/9] clk: qcom: krait-cc: handle secondary mux sourcing out of
PXO
The secondary mux can sourc out of PXO as the secondary MUX is attached
to QSB and to another mux that can source out of PXO or PLL8_VOTE.
Many device may run with uncorrect configuration with the mux sourcing
out of PXO instead of PLL8_VOTE.
To handle this case we add also PXO as required clocks and we check if
the frequency is currently set to PXO and force a correct rate if it's
the case.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index e4fb3ff2b5b5..717eff44b6a4 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -317,7 +317,7 @@ static int krait_cc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *id;
- unsigned long cur_rate, aux_rate, qsb_rate;
+ unsigned long cur_rate, aux_rate, qsb_rate, pxo_rate;
int cpu;
struct clk *clk;
struct clk **clks;
@@ -327,6 +327,15 @@ static int krait_cc_probe(struct platform_device *pdev)
if (!id)
return -ENODEV;
+ clk = clk_get(dev, "pxo");
+ if (IS_ERR(clk))
+ clk = __clk_lookup("pxo_board");
+
+ if (IS_ERR_OR_NULL(clk))
+ return clk == NULL ? -ENODEV : PTR_ERR(clk);
+
+ pxo_rate = clk_get_rate(clk);
+
/*
* Per Documentation qsb should be provided from DTS.
* To address old implementation, register the fixed clock anyway.
@@ -394,6 +403,10 @@ static int krait_cc_probe(struct platform_device *pdev)
dev_info(dev, "L2 @ QSB rate. Forcing new rate.\n");
cur_rate = aux_rate;
}
+ if (cur_rate == pxo_rate) {
+ dev_info(dev, "L2 @ PXO rate. Forcing new rate.\n");
+ cur_rate = aux_rate;
+ }
clk_set_rate(l2_pri_mux_clk, aux_rate);
clk_set_rate(l2_pri_mux_clk, 2);
clk_set_rate(l2_pri_mux_clk, cur_rate);
@@ -405,6 +418,10 @@ static int krait_cc_probe(struct platform_device *pdev)
dev_info(dev, "CPU%d @ QSB rate. Forcing new rate.\n", cpu);
cur_rate = aux_rate;
}
+ if (cur_rate ==pxo_rate) {
+ dev_info(dev, "CPU%d @ PXO rate. Forcing new rate.\n", cpu);
+ cur_rate = aux_rate;
+ }
clk_set_rate(clk, aux_rate);
clk_set_rate(clk, 2);
--
2.37.2

View file

@ -0,0 +1,102 @@
From 6a77cf3f5f95ec0058e1b4d1ada018748cb0b83b Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Thu, 15 Sep 2022 03:33:13 +0200
Subject: [PATCH 9/9] clk: qcom: krait-cc: rework mux reset logic and reset
hfpll
Rework and clean mux reset logic.
Compact it to a for loop to handle both CPU and L2 in one place.
Move hardcoded aux_rate to define and add a new hfpll_rate value to
reset hfpll settings.
Change logic to now reset the hfpll to the lowest value of 600 Mhz and
then restoring the previous frequency. This permits to reset the hfpll if
the primary mux was set to source out of the secondary mux.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/krait-cc.c | 50 +++++++++++++++++--------------------
1 file changed, 23 insertions(+), 27 deletions(-)
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index 717eff44b6a4..90dee71e7c38 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -15,7 +15,9 @@
#include "clk-krait.h"
-#define QSB_RATE 2250000000
+#define QSB_RATE 225000000
+#define AUX_RATE 384000000
+#define HFPLL_RATE 600000000
static unsigned int sec_mux_map[] = {
2,
@@ -317,7 +319,7 @@ static int krait_cc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct of_device_id *id;
- unsigned long cur_rate, aux_rate, qsb_rate, pxo_rate;
+ unsigned long cur_rate, qsb_rate, pxo_rate;
int cpu;
struct clk *clk;
struct clk **clks;
@@ -397,36 +399,30 @@ static int krait_cc_probe(struct platform_device *pdev)
* two different rates to force a HFPLL reinit under all
* circumstances.
*/
- cur_rate = clk_get_rate(l2_pri_mux_clk);
- aux_rate = 384000000;
- if (cur_rate == qsb_rate) {
- dev_info(dev, "L2 @ QSB rate. Forcing new rate.\n");
- cur_rate = aux_rate;
- }
- if (cur_rate == pxo_rate) {
- dev_info(dev, "L2 @ PXO rate. Forcing new rate.\n");
- cur_rate = aux_rate;
- }
- clk_set_rate(l2_pri_mux_clk, aux_rate);
- clk_set_rate(l2_pri_mux_clk, 2);
- clk_set_rate(l2_pri_mux_clk, cur_rate);
- dev_info(dev, "L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
- for_each_possible_cpu(cpu) {
+ for (cpu = 0; cpu < 5; cpu++) {
+ const char *l2_s = "L2";
+ char cpu_s[5];
+
clk = clks[cpu];
+ if (!clk)
+ continue;
+
+ if (cpu < 4)
+ snprintf(cpu_s, 5, "CPU%d", cpu);
+
cur_rate = clk_get_rate(clk);
- if (cur_rate == qsb_rate) {
- dev_info(dev, "CPU%d @ QSB rate. Forcing new rate.\n", cpu);
- cur_rate = aux_rate;
- }
- if (cur_rate ==pxo_rate) {
- dev_info(dev, "CPU%d @ PXO rate. Forcing new rate.\n", cpu);
- cur_rate = aux_rate;
+ if (cur_rate == qsb_rate || cur_rate == pxo_rate) {
+ dev_info(dev, "%s @ %s rate. Forcing new rate.\n",
+ cpu < 4 ? cpu_s : l2_s,
+ cur_rate == qsb_rate ? "QSB" : "PXO");
+ cur_rate = AUX_RATE;
}
- clk_set_rate(clk, aux_rate);
- clk_set_rate(clk, 2);
+ clk_set_rate(clk, AUX_RATE);
+ clk_set_rate(clk, HFPLL_RATE);
clk_set_rate(clk, cur_rate);
- dev_info(dev, "CPU%d @ %lu KHz\n", cpu, clk_get_rate(clk) / 1000);
+ dev_info(dev, "%s @ %lu KHz\n", cpu < 4 ? cpu_s : l2_s,
+ clk_get_rate(clk) / 1000);
}
of_clk_add_provider(dev->of_node, krait_of_get, clks);
--
2.37.2

View file

@ -0,0 +1,156 @@
From 908c361b3c3a139eb3e6a798cb620a6da7514d5c Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Fri, 23 Sep 2022 19:05:39 +0200
Subject: [PATCH 2/4] clk: qcom: clk-krait: generilize div functions
Generilize div functions and remove hardcode to a divisor of 2.
This is just a cleanup and permit to make it more clear the settings of
the devisor when used by the krait-cc driver.
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
drivers/clk/qcom/clk-krait.c | 57 ++++++++++++++++++++----------------
drivers/clk/qcom/clk-krait.h | 11 ++++---
drivers/clk/qcom/krait-cc.c | 7 +++--
3 files changed, 42 insertions(+), 33 deletions(-)
--- a/drivers/clk/qcom/clk-krait.c
+++ b/drivers/clk/qcom/clk-krait.c
@@ -97,53 +97,58 @@ const struct clk_ops krait_mux_clk_ops =
EXPORT_SYMBOL_GPL(krait_mux_clk_ops);
/* The divider can divide by 2, 4, 6 and 8. But we only really need div-2. */
-static long krait_div2_round_rate(struct clk_hw *hw, unsigned long rate,
+static long krait_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
- *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), rate * 2);
- return DIV_ROUND_UP(*parent_rate, 2);
+ struct krait_div_clk *d = to_krait_div_clk(hw);
+
+ *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+ rate * d->divisor);
+
+ return DIV_ROUND_UP(*parent_rate, d->divisor);
}
-static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
+static int krait_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
- struct krait_div2_clk *d = to_krait_div2_clk(hw);
+ struct krait_div_clk *d = to_krait_div_clk(hw);
+ u8 div_val = krait_div_to_val(d->divisor);
unsigned long flags;
- u32 val;
- u32 mask = BIT(d->width) - 1;
-
- if (d->lpl)
- mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
- else
- mask <<= d->shift;
+ u32 regval;
spin_lock_irqsave(&krait_clock_reg_lock, flags);
- val = krait_get_l2_indirect_reg(d->offset);
- val &= ~mask;
- krait_set_l2_indirect_reg(d->offset, val);
+ regval = krait_get_l2_indirect_reg(d->offset);
+
+ regval &= ~(d->mask << d->shift);
+ regval |= (div_val & d->mask) << d->shift;
+
+ if (d->lpl) {
+ regval &= ~(d->mask << (d->shift + LPL_SHIFT));
+ regval |= (div_val & d->mask) << (d->shift + LPL_SHIFT);
+ }
+
+ krait_set_l2_indirect_reg(d->offset, regval);
spin_unlock_irqrestore(&krait_clock_reg_lock, flags);
return 0;
}
static unsigned long
-krait_div2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+krait_div_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
- struct krait_div2_clk *d = to_krait_div2_clk(hw);
- u32 mask = BIT(d->width) - 1;
+ struct krait_div_clk *d = to_krait_div_clk(hw);
u32 div;
div = krait_get_l2_indirect_reg(d->offset);
div >>= d->shift;
- div &= mask;
- div = (div + 1) * 2;
+ div &= d->mask;
- return DIV_ROUND_UP(parent_rate, div);
+ return DIV_ROUND_UP(parent_rate, krait_val_to_div(div));
}
-const struct clk_ops krait_div2_clk_ops = {
- .round_rate = krait_div2_round_rate,
- .set_rate = krait_div2_set_rate,
- .recalc_rate = krait_div2_recalc_rate,
+const struct clk_ops krait_div_clk_ops = {
+ .round_rate = krait_div_round_rate,
+ .set_rate = krait_div_set_rate,
+ .recalc_rate = krait_div_recalc_rate,
};
-EXPORT_SYMBOL_GPL(krait_div2_clk_ops);
+EXPORT_SYMBOL_GPL(krait_div_clk_ops);
--- a/drivers/clk/qcom/clk-krait.h
+++ b/drivers/clk/qcom/clk-krait.h
@@ -25,17 +25,20 @@ struct krait_mux_clk {
extern const struct clk_ops krait_mux_clk_ops;
-struct krait_div2_clk {
+struct krait_div_clk {
u32 offset;
- u8 width;
+ u32 mask;
+ u8 divisor;
u32 shift;
bool lpl;
struct clk_hw hw;
};
-#define to_krait_div2_clk(_hw) container_of(_hw, struct krait_div2_clk, hw)
+#define to_krait_div_clk(_hw) container_of(_hw, struct krait_div_clk, hw)
+#define krait_div_to_val(_div) ((_div) / 2) - 1
+#define krait_val_to_div(_val) ((_val) + 1) * 2
-extern const struct clk_ops krait_div2_clk_ops;
+extern const struct clk_ops krait_div_clk_ops;
#endif
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -76,11 +76,11 @@ static int krait_notifier_register(struc
static struct clk *
krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
{
- struct krait_div2_clk *div;
+ struct krait_div_clk *div;
static struct clk_parent_data p_data[1];
struct clk_init_data init = {
.num_parents = ARRAY_SIZE(p_data),
- .ops = &krait_div2_clk_ops,
+ .ops = &krait_div_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
struct clk *clk;
@@ -90,7 +90,8 @@ krait_add_div(struct device *dev, int id
if (!div)
return ERR_PTR(-ENOMEM);
- div->width = 2;
+ div->mask = 0x3;
+ div->divisor = 2;
div->shift = 6;
div->lpl = id >= 0;
div->offset = offset;

View file

@ -0,0 +1,26 @@
From f7b300f770683cd063f922e43fa4ad818761c1fb Mon Sep 17 00:00:00 2001
From: Christian Marangi <ansuelsmth@gmail.com>
Date: Sat, 22 Oct 2022 16:55:21 +0200
Subject: [PATCH] ARM: dts: qcom: ipq8064: disable mmc-ddr-1_8v for sdcc1
It was reported non working mmc with this option enabled.
Both mmc for ipq8064 are supplied by a fixed 3.3v regulator so mmc can't
be run at 1.8v.
Disable it to restore correct functionality of this SoC feature.
Tested-by: Hendrik Koerner <koerhen@web.de>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
---
arch/arm/boot/dts/qcom-ipq8064.dtsi | 1 -
1 file changed, 1 deletion(-)
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -1529,7 +1529,6 @@
non-removable;
cap-sd-highspeed;
cap-mmc-highspeed;
- mmc-ddr-1_8v;
vmmc-supply = <&vsdcc_fixed>;
dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
dma-names = "tx", "rx";

View file

@ -0,0 +1,121 @@
From: Christian Lamparter <chunkeey@googlemail.com>
Subject: SoC: add qualcomm syscon
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o
obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
+obj-$(CONFIG_QCOM_TCSR) += qcom_tcsr.o
obj-$(CONFIG_QCOM_APR) += apr.o
obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -190,6 +190,13 @@ config QCOM_SOCINFO
Say yes here to support the Qualcomm socinfo driver, providing
information about the SoC to user space.
+config QCOM_TCSR
+ tristate "QCOM Top Control and Status Registers"
+ depends on ARCH_QCOM
+ help
+ Say y here to enable TCSR support. The TCSR provides control
+ functions for various peripherals.
+
config QCOM_WCNSS_CTRL
tristate "Qualcomm WCNSS control driver"
depends on ARCH_QCOM || COMPILE_TEST
--- /dev/null
+++ b/drivers/soc/qcom/qcom_tcsr.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2014, The Linux foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License rev 2 and
+ * only rev 2 as published by the free Software foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#define TCSR_USB_PORT_SEL 0xb0
+
+static int tcsr_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ const struct device_node *node = pdev->dev.of_node;
+ void __iomem *base;
+ u32 val;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ if (!of_property_read_u32(node, "qcom,usb-ctrl-select", &val)) {
+ dev_err(&pdev->dev, "setting usb port select = %d\n", val);
+ writel(val, base + TCSR_USB_PORT_SEL);
+ }
+
+ return 0;
+}
+
+static const struct of_device_id tcsr_dt_match[] = {
+ { .compatible = "qcom,tcsr", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, tcsr_dt_match);
+
+static struct platform_driver tcsr_driver = {
+ .driver = {
+ .name = "tcsr",
+ .owner = THIS_MODULE,
+ .of_match_table = tcsr_dt_match,
+ },
+ .probe = tcsr_probe,
+};
+
+module_platform_driver(tcsr_driver);
+
+MODULE_AUTHOR("Andy Gross <agross@codeaurora.org>");
+MODULE_DESCRIPTION("QCOM TCSR driver");
+MODULE_LICENSE("GPL v2");
--- /dev/null
+++ b/include/dt-bindings/soc/qcom,tcsr.h
@@ -0,0 +1,23 @@
+/* Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __DT_BINDINGS_QCOM_TCSR_H
+#define __DT_BINDINGS_QCOM_TCSR_H
+
+#define TCSR_USB_SELECT_USB3_P0 0x1
+#define TCSR_USB_SELECT_USB3_P1 0x2
+#define TCSR_USB_SELECT_USB3_DUAL 0x3
+
+/* TCSR A/B REG */
+#define IPQ806X_TCSR_REG_A_ADM_CRCI_MUX_SEL 0
+#define IPQ806X_TCSR_REG_B_ADM_CRCI_MUX_SEL 1
+
+#endif