[PATCH] efi_loader: add /dtbs search path

2024-07-22 Thread Caleb Connolly
Add an additional search path /dtbs, this is where dtbs are installed on
postmarketOS and potentially other distros.

Signed-off-by: Caleb Connolly 
---
 lib/efi_loader/efi_fdt.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c
index 86ba00c2bdd9..4777943b80df 100644
--- a/lib/efi_loader/efi_fdt.c
+++ b/lib/efi_loader/efi_fdt.c
@@ -42,8 +42,11 @@ int efi_get_distro_fdt_name(char *fname, int size, int seq)
break;
case 2:
prefix = "/dtb/current";
break;
+   case 3:
+   prefix = "/dtbs";
+   break;
default:
return log_msg_ret("pref", -EINVAL);
}
 
-- 
2.45.2



Re: [PATCH v6 06/24] soc: qcom: cmd-db: adjust probe for U-Boot

2024-07-19 Thread Caleb Connolly




On 19/07/2024 17:04, Simon Glass wrote:

Hi Caleb,

On Tue, 16 Jul 2024 at 08:16, Caleb Connolly  wrote:




On 16/07/2024 09:04, Simon Glass wrote:

Hi Caleb,

On Mon, 15 Jul 2024 at 22:42, Caleb Connolly  wrote:




On 15/07/2024 13:39, Simon Glass wrote:

On Mon, 15 Jul 2024 at 11:08, Caleb Connolly  wrote:


Integrate cmd-db into the U-Boot driver model.

This is just a wrapper around an in-memory database, so we just need to
get the address and validate that cmd-db is there.

Since cmd_db_header will be stored in the .data section we can skip
bind if it's already set.

Signed-off-by: Caleb Connolly 
---
To: Simon Glass 
---
drivers/soc/qcom/cmd-db.c | 72 
+++
include/soc/qcom/cmd-db.h |  3 --
2 files changed, 23 insertions(+), 52 deletions(-)



Reviewed-by: Simon Glass 


Thanks


BTW, this is a MISC driver. Does it implement the read() operation?


No, the API (as defined in the header file) takes a string and returns a
database entry. cmd-db users don't have an easily available handle to
the node / udevice regardless.


OK. The closest thing might be UCLASS_SYSINFO, but it is designed for
inside U-Boot and uses an int instead of a string for lookup.


Right, I don't think we'll be able to find a more optimum solution here.


OK



Could you use the devicetree for this information? What sort of info is it?


It maps resource names (e.g. "ldoa1" - the LDO1 regulator on PMIC A) to
the address of the resource on the RPMh co-processor.

We need to support existing (upstream) devicetree, since this has
already been around for many years.


OK., Has this problem been resolved in more recent platforms?


What problem?


Regards,
Simon


--
// Caleb (they/them)


[PATCH v5 09/11] tools: mkeficapsule: support generating dynamic GUIDs

2024-07-19 Thread Caleb Connolly
Add support for generating GUIDs that match those generated internally
by U-Boot for capsule update fw_images when using dynamic UUIDs.

Dynamic UUIDs in U-Boot work by taking a namespace UUID and hashing it
with the board compatible and fw_image name. This feature just provides
a way to determine the UUIDs for a particular board without having to
actually boot U-Boot on it.

Signed-off-by: Caleb Connolly 
---
 doc/mkeficapsule.1   |  23 
 tools/mkeficapsule.c | 156 +--
 2 files changed, 174 insertions(+), 5 deletions(-)

diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
index c4c2057d5c7a..bf735295effa 100644
--- a/doc/mkeficapsule.1
+++ b/doc/mkeficapsule.1
@@ -9,8 +9,11 @@ mkeficapsule \- Generate EFI capsule file for U-Boot
 .SH SYNOPSIS
 .B mkeficapsule
 .RI [ options ] " " [ image-blob ] " " capsule-file
 
+.B mkeficapsule
+.RI guidgen " " [ GUID ] " " DTB " " IMAGE_NAME...
+
 .SH "DESCRIPTION"
 The
 .B mkeficapsule
 command is used to create an EFI capsule file to be used by U-Boot for firmware
@@ -41,8 +44,12 @@ format is the same as used in the new uImage format and 
allows for
 multiple binary blobs in a single capsule file.
 This type of image file can be generated by
 .BR mkimage .
 
+mkeficapsule can also be used to simulate the dynamic GUID generation used to
+identify firmware images in capsule updates by providing the namespace guid, 
dtb
+for the board, and a list of firmware images.
+
 .SH "OPTIONS"
 
 .TP
 .BI "-g\fR,\fB --guid " guid-string
@@ -112,8 +119,24 @@ at every firmware update.
 .TP
 .B "-d\fR,\fB --dump_sig"
 Dump signature data into *.p7 file
 
+.SH "GUIDGEN OPTIONS"
+
+.TP
+.B "[GUID]"
+The namespace/salt GUID, by default this is EFI_CAPSULE_NAMESPACE_GUID.
+The format is:
+----
+
+.TP
+.B DTB
+The device tree blob file for the board.
+
+.TP
+.B IMAGE_NAME...
+The names of the firmware images to generate GUIDs for.
+
 .PP
 .SH FILES
 .TP
 .I /EFI/UpdateCapsule
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 54fb4dee3ee5..8dfc09ffaf4f 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -19,12 +19,16 @@
 #include 
 #include 
 #include 
 
+#include 
 #include 
 
 #include "eficapsule.h"
 
+// Matches CONFIG_EFI_CAPSULE_NAMESPACE_GUID
+#define DEFAULT_NAMESPACE_GUID "8c9f137e-91dc-427b-b2d6-b420faebaf2a"
+
 static const char *tool_name = "mkeficapsule";
 
 efi_guid_t efi_guid_fm_capsule = EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
@@ -53,11 +57,23 @@ static struct option options[] = {
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0},
 };
 
-static void print_usage(void)
+
+static void print_usage_guidgen(void)
 {
-   fprintf(stderr, "Usage: %s [options]  \n"
+   fprintf(stderr, "%s guidgen [GUID] DTB IMAGE_NAME...\n"
+   "Options:\n"
+
+   "\tGUIDNamespace GUID (default: %s)\n"
+   "\tDTB Device Tree Blob\n"
+   "\tIMAGE_NAME...   One or more names of fw_images 
to generate GUIDs for\n",
+   tool_name, DEFAULT_NAMESPACE_GUID);
+}
+
+static void print_usage_mkeficapsule(void)
+{
+   fprintf(stderr, "Usage: \n\n%s [options]  \n"
"Options:\n"
 
"\t-g, --guid guid for image blob type\n"
"\t-i, --index  update image index\n"
@@ -70,10 +86,11 @@ static void print_usage(void)
"\t-A, --fw-accept  firmware accept capsule, requires GUID, no 
image blob\n"
"\t-R, --fw-revert  firmware revert capsule, takes no GUID, no 
image blob\n"
"\t-o, --capoemflag Capsule OEM Flag, an integer between 0x 
and 0x\n"
"\t-D, --dump-capsule  dump the contents of the capsule 
headers\n"
-   "\t-h, --help  print a help message\n",
+   "\t-h, --help  print a help message\n\n",
tool_name);
+   print_usage_guidgen();
 }
 
 /**
  * auth_context - authentication context
@@ -816,8 +833,130 @@ static void dump_capsule_contents(char *capsule_file)
exit(EXIT_FAILURE);
}
 }
 
+static struct fdt_header *load_dtb(const char *path)
+{
+   struct fdt_header *dtb;
+   ssize_t dtb_size;
+   FILE *f;
+
+   /* Open and parse DTB */
+   f = fopen(path, "r");
+   if (!f) {
+   fprintf(stderr, "Cannot open %s\n", path);
+   return NULL;
+   }
+
+   if (fseek(f, 0, 

[PATCH v5 08/11] tools: mkeficapsule: use u-boot UUID library

2024-07-19 Thread Caleb Connolly
Replace the use of libuuid with U-Boot's own UUID library. This prepares
us to add support for generating v5 GUIDs.

Signed-off-by: Caleb Connolly 
---
 tools/Makefile   |  8 
 tools/mkeficapsule.c | 53 ++--
 2 files changed, 10 insertions(+), 51 deletions(-)

diff --git a/tools/Makefile b/tools/Makefile
index 6a4280e3668f..ee08a9675df8 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -245,14 +245,14 @@ hostprogs-$(CONFIG_ASN1_COMPILER) += asn1_compiler
 HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
 
 HOSTCFLAGS_mkeficapsule.o += \
$(shell pkg-config --cflags gnutls 2> /dev/null || echo "")
-HOSTCFLAGS_mkeficapsule.o += \
-   $(shell pkg-config --cflags uuid 2> /dev/null || echo "")
 HOSTLDLIBS_mkeficapsule += \
$(shell pkg-config --libs gnutls 2> /dev/null || echo "-lgnutls")
-HOSTLDLIBS_mkeficapsule += \
-   $(shell pkg-config --libs uuid 2> /dev/null || echo "-luuid")
+mkeficapsule-objs := generated/lib/uuid.o \
+   generated/lib/sha1.o \
+   $(LIBFDT_OBJS) \
+   mkeficapsule.o
 hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
 
 mkfwumdata-objs := mkfwumdata.o generated/lib/crc32.o
 HOSTLDLIBS_mkfwumdata += -luuid
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 6a261ff549dc..54fb4dee3ee5 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -14,14 +14,15 @@
 #include 
 
 #include 
 #include 
-#include 
 
 #include 
 #include 
 #include 
 
+#include 
+
 #include "eficapsule.h"
 
 static const char *tool_name = "mkeficapsule";
 
@@ -573,39 +574,8 @@ err:
 
return ret;
 }
 
-/**
- * convert_uuid_to_guid() - convert UUID to GUID
- * @buf:   UUID binary
- *
- * UUID and GUID have the same data structure, but their binary
- * formats are different due to the endianness. See lib/uuid.c.
- * Since uuid_parse() can handle only UUID, this function must
- * be called to get correct data for GUID when parsing a string.
- *
- * The correct data will be returned in @buf.
- */
-void convert_uuid_to_guid(unsigned char *buf)
-{
-   unsigned char c;
-
-   c = buf[0];
-   buf[0] = buf[3];
-   buf[3] = c;
-   c = buf[1];
-   buf[1] = buf[2];
-   buf[2] = c;
-
-   c = buf[4];
-   buf[4] = buf[5];
-   buf[5] = c;
-
-   c = buf[6];
-   buf[6] = buf[7];
-   buf[7] = c;
-}
-
 static int create_empty_capsule(char *path, efi_guid_t *guid, bool fw_accept)
 {
struct efi_capsule_header header = { 0 };
FILE *f = NULL;
@@ -649,22 +619,12 @@ err:
 }
 
 static void print_guid(void *ptr)
 {
-   int i;
-   efi_guid_t *guid = ptr;
-   const uint8_t seq[] = {
-   3, 2, 1, 0, '-', 5, 4, '-', 7, 6,
-   '-', 8, 9, '-', 10, 11, 12, 13, 14, 15 };
+   static char buf[37] = { 0 };
 
-   for (i = 0; i < ARRAY_SIZE(seq); i++) {
-   if (seq[i] == '-')
-   putchar(seq[i]);
-   else
-   printf("%02X", guid->b[seq[i]]);
-   }
-
-   printf("\n");
+   uuid_bin_to_str(ptr, buf, UUID_STR_FORMAT_GUID|UUID_STR_UPPER_CASE);
+   printf("%s\n", buf);
 }
 
 static uint32_t dump_fmp_payload_header(
struct fmp_payload_header *fmp_payload_hdr)
@@ -902,13 +862,12 @@ int main(int argc, char **argv)
fprintf(stderr,
"Image type already specified\n");
exit(EXIT_FAILURE);
}
-   if (uuid_parse(optarg, uuid_buf)) {
+   if (uuid_str_to_bin(optarg, uuid_buf, 
UUID_STR_FORMAT_GUID)) {
fprintf(stderr, "Wrong guid format\n");
exit(EXIT_FAILURE);
}
-   convert_uuid_to_guid(uuid_buf);
guid = (efi_guid_t *)uuid_buf;
break;
case 'i':
index = strtoul(optarg, NULL, 0);

-- 
2.45.2



[PATCH v5 11/11] test: lib/uuid: add tests for UUID version/variant bits

2024-07-19 Thread Caleb Connolly
Add a test to check the version/variant bits of v4 and v5 UUIDs.

Signed-off-by: Caleb Connolly 
---
 test/lib/uuid.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/test/lib/uuid.c b/test/lib/uuid.c
index 2c6cfd42ddc3..63d36e120623 100644
--- a/test/lib/uuid.c
+++ b/test/lib/uuid.c
@@ -43,8 +43,44 @@ static int lib_test_uuid_to_le(struct unit_test_state *uts)
 }
 
 LIB_TEST(lib_test_uuid_to_le, 0);
 
+/* Test UUID attribute bits (version, variant) */
+static int lib_test_uuid_bits(struct unit_test_state *uts)
+{
+   unsigned char uuid[16];
+   efi_guid_t guid;
+   int i;
+
+   /*
+* Reduce the chance of a randomly generated UUID disguising
+* a regression by testing multiple times.
+*/
+   for (i = 0; i < 5; i++) {
+   /* Test UUID v4 */
+   gen_rand_uuid((unsigned char *));
+
+   printf("v4 UUID: %pUb\n", (efi_guid_t *)uuid);
+
+   ut_assert((uuid[6] & 0xf0) == 0x40); /* version 4 */
+   ut_assert((uuid[8] & UUID_VARIANT_MASK) == (UUID_VARIANT << 
UUID_VARIANT_SHIFT)); /* variant 1 */
+
+   /* Test v5, use the v4 UUID as the namespace */
+   gen_v5_guid((struct uuid *)uuid,
+   , "test", 4, NULL);
+
+   printf("v5 GUID: %pUl\n", (efi_guid_t *)uuid);
+
+   /* This is a GUID so bits 6 and 7 are swapped (little endian) */
+   ut_assert((guid.b[7] & 0xf0) == 0x50); /* version 5 */
+   ut_assert((guid.b[8] & UUID_VARIANT_MASK) == (UUID_VARIANT << 
UUID_VARIANT_SHIFT)); /* variant 1 */
+   }
+
+   return 0;
+}
+
+LIB_TEST(lib_test_uuid_bits, 0);
+
 struct dynamic_uuid_test_data {
const char *compatible;
const u16 *images[4];
const char *expected_uuids[4];

-- 
2.45.2



[PATCH v5 10/11] test: lib/uuid: add unit tests for dynamic UUIDs

2024-07-19 Thread Caleb Connolly
Add some basic unit tests to validate that the UUID generation behaves
as expected. This matches the implementation in efi_loader for sandbox
and a Qualcomm board and should catch any regressions.

Signed-off-by: Caleb Connolly 
---
 test/lib/uuid.c | 82 +
 1 file changed, 82 insertions(+)

diff --git a/test/lib/uuid.c b/test/lib/uuid.c
index 9629d378c329..2c6cfd42ddc3 100644
--- a/test/lib/uuid.c
+++ b/test/lib/uuid.c
@@ -7,15 +7,20 @@
  * Authors:
  *   Abdellatif El Khlifi 
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 /* test UUID */
 #define TEST_SVC_UUID  "ed32d533-4209-99e6-2d72-cdd998a79cc0"
+/* U-Boot default fw image namespace */
+#define DEFAULT_FW_IMAGE_NAMESPACE "8c9f137e-91dc-427b-b2d6-b420faebaf2a"
 
 #define UUID_SIZE 16
 
 /* The UUID binary data (little-endian format) */
@@ -37,4 +42,81 @@ static int lib_test_uuid_to_le(struct unit_test_state *uts)
return 0;
 }
 
 LIB_TEST(lib_test_uuid_to_le, 0);
+
+struct dynamic_uuid_test_data {
+   const char *compatible;
+   const u16 *images[4];
+   const char *expected_uuids[4];
+};
+
+static int lib_test_dynamic_uuid_case(struct unit_test_state *uts,
+ const struct dynamic_uuid_test_data *data)
+{
+   struct uuid namespace;
+   int j;
+
+   ut_assertok(uuid_str_to_bin(DEFAULT_FW_IMAGE_NAMESPACE, (unsigned char 
*),
+   UUID_STR_FORMAT_GUID));
+
+   for (j = 0; data->images[j]; j++) {
+   const char *expected_uuid = data->expected_uuids[j];
+   const u16 *image = data->images[j];
+   efi_guid_t uuid;
+   char uuid_str[37];
+
+   gen_v5_guid(, ,
+   data->compatible, strlen(data->compatible),
+   image, u16_strlen(image) * sizeof(uint16_t),
+   NULL);
+   uuid_bin_to_str((unsigned char *), uuid_str, 
UUID_STR_FORMAT_GUID);
+
+   ut_asserteq_str(expected_uuid, uuid_str);
+   }
+
+   return 0;
+}
+
+static int lib_test_dynamic_uuid(struct unit_test_state *uts)
+{
+   int ret, i;
+   const struct dynamic_uuid_test_data test_data[] = {
+   {
+   .compatible = "sandbox",
+   .images = {
+   u"SANDBOX-UBOOT",
+   u"SANDBOX-UBOOT-ENV",
+   u"SANDBOX-FIT",
+   NULL,
+   },
+   .expected_uuids = {
+   "985f2937-7c2e-5e9a-8a5e-8e063312964b",
+   "9e339473-c2eb-530a-a69b-0cd6bbbed40e",
+   "46610520-469e-59dc-a8dd-c11832b877ea",
+   NULL,
+   }
+   },
+   {
+   .compatible = "qcom,qrb4210-rb2",
+   .images = {
+   u"QUALCOMM-UBOOT",
+   NULL,
+   },
+   .expected_uuids = {
+   "d5021fac-8dd0-5ed7-90c2-763c304aaf86",
+   NULL,
+   }
+   },
+   };
+
+   for (i = 0; i < ARRAY_SIZE(test_data); i++) {
+   ret = lib_test_dynamic_uuid_case(uts, _data[i]);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+
+LIB_TEST(lib_test_dynamic_uuid, 0);
+

-- 
2.45.2



[PATCH v5 07/11] include: export uuid.h

2024-07-19 Thread Caleb Connolly
Move this header to include/u-boot/ so that it can be used by external
tools.

Signed-off-by: Caleb Connolly 
---
 arch/arm/mach-rockchip/board.c | 2 +-
 board/cobra5272/flash.c| 2 +-
 board/gardena/smart-gateway-mt7688/board.c | 2 +-
 board/socrates/socrates.c  | 2 +-
 board/xilinx/common/board.c| 2 +-
 cmd/efi.c  | 2 +-
 cmd/efi_common.c   | 2 +-
 cmd/flash.c| 2 +-
 cmd/gpt.c  | 2 +-
 cmd/nvedit_efi.c   | 2 +-
 cmd/x86/hob.c  | 2 +-
 common/flash.c | 2 +-
 disk/part_efi.c| 2 +-
 drivers/firmware/arm-ffa/arm-ffa-uclass.c  | 2 +-
 env/sf.c   | 2 +-
 fs/btrfs/btrfs.c   | 2 +-
 fs/btrfs/compat.h  | 2 +-
 fs/btrfs/disk-io.c | 2 +-
 fs/ext4/ext4fs.c   | 2 +-
 include/fwu.h  | 2 +-
 include/part.h | 2 +-
 include/rkmtd.h| 2 +-
 include/{ => u-boot}/uuid.h| 0
 lib/acpi/acpi_dp.c | 2 +-
 lib/acpi/acpigen.c | 2 +-
 lib/efi/efi_app.c  | 2 +-
 lib/efi_loader/efi_capsule.c   | 2 +-
 lib/efi_loader/efi_device_path.c   | 2 +-
 lib/efi_loader/efi_variable.c  | 2 +-
 lib/fwu_updates/fwu_mtd.c  | 2 +-
 lib/uuid.c | 2 +-
 lib/vsprintf.c | 2 +-
 net/bootp.c| 2 +-
 test/dm/acpi_dp.c  | 2 +-
 test/dm/acpigen.c  | 2 +-
 test/lib/uuid.c| 2 +-
 36 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c
index 8a57b8217ff2..0fdf9365b41e 100644
--- a/arch/arm/mach-rockchip/board.c
+++ b/arch/arm/mach-rockchip/board.c
@@ -24,9 +24,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
diff --git a/board/cobra5272/flash.c b/board/cobra5272/flash.c
index 157b71da85e8..0c1b1c7decd8 100644
--- a/board/cobra5272/flash.c
+++ b/board/cobra5272/flash.c
@@ -10,9 +10,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 
diff --git a/board/gardena/smart-gateway-mt7688/board.c 
b/board/gardena/smart-gateway-mt7688/board.c
index c6b14bed41fb..eb7fcd630a10 100644
--- a/board/gardena/smart-gateway-mt7688/board.c
+++ b/board/gardena/smart-gateway-mt7688/board.c
@@ -15,9 +15,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 
 #define MT76XX_AGPIO_CFG   0x103c
diff --git a/board/socrates/socrates.c b/board/socrates/socrates.c
index 6e6e276cc741..5e5a45ee00db 100644
--- a/board/socrates/socrates.c
+++ b/board/socrates/socrates.c
@@ -14,9 +14,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
diff --git a/board/xilinx/common/board.c b/board/xilinx/common/board.c
index 0b43407b9e94..8cec455ae984 100644
--- a/board/xilinx/common/board.c
+++ b/board/xilinx/common/board.c
@@ -30,9 +30,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #include "fru.h"
 
 #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
diff --git a/cmd/efi.c b/cmd/efi.c
index 6bed2d743ba6..687ccb520428 100644
--- a/cmd/efi.c
+++ b/cmd/efi.c
@@ -10,9 +10,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
diff --git a/cmd/efi_common.c b/cmd/efi_common.c
index c46764e6eea7..d2f2b59e9e3b 100644
--- a/cmd/efi_common.c
+++ b/cmd/efi_common.c
@@ -7,9 +7,9 @@
  */
 
 #include 
 #include 
-#include 
+#include 
 
 void efi_show_tables(struct efi_system_table *systab)
 {
int i;
diff --git a/cmd/flash.c b/cmd/flash.c
index de0e04f09cfb..fd660ec477c9 100644
--- a/cmd/flash.c
+++ b/cmd/flash.c
@@ -9,9 +9,9 @@
  */
 #include 
 #include 
 #include 
-#include 
+#include 
 
 #if defined(CONFIG_CMD_MTDPARTS)
 #include 
 
diff --git a/cmd/gpt.c b/cmd/gpt.c
index 86b7701886a3..27aea2df197c 100644
--- a/cmd/gpt.c
+++ b/cmd/gpt.c
@@ -18,9 +18,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c
index 64ae2ad2ce24..32b7d0490747 100644
--- a/cmd/nvedit_efi.c
+++ b/cmd/nvedit_efi.c
@@ -14,9 +14,9 @@
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 #include 
 
 /*
  * From efi_variable.c,
diff --git a/cmd/x86/hob.c b/cmd/x86/hob.c
index 2dd30808bd10..d3713cef3312 100644
--- a/cmd/x86/hob.c
+++ b/

[PATCH v5 06/11] lib: uuid: supporting building as part of host tools

2024-07-19 Thread Caleb Connolly
Adjust the UUID library code so that it can be compiled as part of a
host tool.

This removes the one redundant log_debug() call, as well as the
incorrectly defined LOG_CATEGORY.

In general this is a fairly trivial change, just adjusting includes and
disabling list_guid.

This will be used by a new genguid tool to generate v5 GUIDs that match
those generated by U-Boot at runtime.

Signed-off-by: Caleb Connolly 
---
 include/uuid.h |  4 ++--
 lib/uuid.c | 44 ++--
 2 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/include/uuid.h b/include/uuid.h
index 1f4fa103b5e9..7f8414dc906c 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -69,10 +69,10 @@ struct uuid {
 } __packed;
 
 /* Bits of a bitmask specifying the output format for GUIDs */
 #define UUID_STR_FORMAT_STD0
-#define UUID_STR_FORMAT_GUID   BIT(0)
-#define UUID_STR_UPPER_CASEBIT(1)
+#define UUID_STR_FORMAT_GUID   0x1
+#define UUID_STR_UPPER_CASE0x2
 
 /* Use UUID_STR_LEN + 1 for string space */
 #define UUID_STR_LEN   36
 #define UUID_BIN_LEN   sizeof(struct uuid)
diff --git a/lib/uuid.c b/lib/uuid.c
index 7d0a8273d157..272e07dc1613 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -6,25 +6,38 @@
  * Authors:
  *   Abdellatif El Khlifi 
  */
 
-#define LOG_CATEGOT LOGC_CORE
-
+#ifndef USE_HOSTCC
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
-#include 
-#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
+#include 
+#else
+#include 
+#include 
+#include 
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
 #include 
 
+#ifdef USE_HOSTCC
+/* polyfill hextoul to avoid pulling in strto.c */
+#define hextoul(cp, endp) strtoul(cp, endp, 16)
+#endif
+
 int uuid_str_valid(const char *uuid)
 {
int i, valid;
 
@@ -51,8 +64,9 @@ int uuid_str_valid(const char *uuid)
 static const struct {
const char *string;
efi_guid_t guid;
 } list_guid[] = {
+#ifndef USE_HOSTCC
 #ifdef CONFIG_PARTITION_TYPE_GUID
{"system",  PARTITION_SYSTEM_GUID},
{"mbr", LEGACY_MBR_PARTITION_GUID},
{"msft",PARTITION_MSFT_RESERVED_GUID},
@@ -231,8 +245,9 @@ static const struct {
{ "EFI_MEMORY_TYPE", EFI_MEMORY_TYPE },
{ "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC },
{ "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 },
 #endif
+#endif /* !USE_HOSTCC */
 };
 
 int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin)
 {
@@ -266,9 +281,8 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char 
*uuid_bin,
uint32_t tmp32;
uint64_t tmp64;
 
if (!uuid_str_valid(uuid_str)) {
-   log_debug("not valid\n");
 #ifdef CONFIG_PARTITION_TYPE_GUID
if (!uuid_guid_get_bin(uuid_str, uuid_bin))
return 0;
 #endif
@@ -297,19 +311,19 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char 
*uuid_bin,
 
tmp16 = cpu_to_be16(hextoul(uuid_str + 19, NULL));
memcpy(uuid_bin + 8, , 2);
 
-   tmp64 = cpu_to_be64(simple_strtoull(uuid_str + 24, NULL, 16));
+   tmp64 = cpu_to_be64(hextoul(uuid_str + 24, NULL));
memcpy(uuid_bin + 10, (char *) + 2, 6);
 
return 0;
 }
 
 int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin)
 {
-   u16 tmp16;
-   u32 tmp32;
-   u64 tmp64;
+   uint16_t tmp16;
+   uint32_t tmp32;
+   uint64_t tmp64;
 
if (!uuid_str_valid(uuid_str) || !uuid_bin)
return -EINVAL;
 
@@ -324,22 +338,22 @@ int uuid_str_to_le_bin(const char *uuid_str, unsigned 
char *uuid_bin)
 
tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL));
memcpy(uuid_bin + 8, , 2);
 
-   tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16));
+   tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL));
memcpy(uuid_bin + 10, , 6);
 
return 0;
 }
 
 void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str,
 int str_format)
 {
-   const u8 uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8,
+   const uint8_t uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 
8,
  9, 10, 11, 12, 13, 14, 15};
-   const u8 guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8,
+   const uint8_t guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 
8,
  9, 10, 11, 12, 13, 14, 15};
-   const u8 *char_order;
+   const uint8_t *char_order;
const char *format;
int i;
 
/*
@@ -418,8 +432,9 @@ void gen_v5_guid(const struct uuid *namespace, struct 
efi_guid *guid, ...)
tmp16 = (uint16_t *)>b[6];
*tmp16 = be16_to_cpu(*tmp16);
 }
 
+#ifndef USE_HOSTCC
 #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
 void gen_rand_uuid(unsigned c

[PATCH v5 05/11] sandbox: switch to dynamic UUIDs

2024-07-19 Thread Caleb Connolly
Migrate sandbox over to generating it's capsule update image GUIDs
dynamically from the namespace and board/image info. Update the
reference and tests to use the new GUIDs.

Signed-off-by: Caleb Connolly 
---
 board/sandbox/sandbox.c  | 16 
 include/sandbox_efi_capsule.h|  6 +++---
 .../tests/test_efi_capsule/test_capsule_firmware_fit.py  |  2 +-
 .../tests/test_efi_capsule/test_capsule_firmware_raw.py  |  8 
 .../test_efi_capsule/test_capsule_firmware_signed_fit.py |  2 +-
 .../test_efi_capsule/test_capsule_firmware_signed_raw.py |  4 ++--
 test/py/tests/test_efi_capsule/version.dts   |  6 +++---
 tools/binman/etype/efi_capsule.py|  2 +-
 tools/binman/ftest.py|  2 +-
 9 files changed, 16 insertions(+), 32 deletions(-)

diff --git a/board/sandbox/sandbox.c b/board/sandbox/sandbox.c
index 802596569c64..d97945e58fcf 100644
--- a/board/sandbox/sandbox.c
+++ b/board/sandbox/sandbox.c
@@ -31,36 +31,20 @@
  */
 gd_t *gd;
 
 #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
-/* GUIDs for capsule updatable firmware images */
-#define SANDBOX_UBOOT_IMAGE_GUID \
-   EFI_GUID(0x09d7cf52, 0x0720, 0x4710, 0x91, 0xd1, \
-0x08, 0x46, 0x9b, 0x7f, 0xe9, 0xc8)
-
-#define SANDBOX_UBOOT_ENV_IMAGE_GUID \
-   EFI_GUID(0x5a7021f5, 0xfef2, 0x48b4, 0xaa, 0xba, \
-0x83, 0x2e, 0x77, 0x74, 0x18, 0xc0)
-
-#define SANDBOX_FIT_IMAGE_GUID \
-   EFI_GUID(0x3673b45d, 0x6a7c, 0x46f3, 0x9e, 0x60, \
-0xad, 0xab, 0xb0, 0x3f, 0x79, 0x37)
-
 struct efi_fw_image fw_images[] = {
 #if defined(CONFIG_EFI_CAPSULE_FIRMWARE_RAW)
{
-   .image_type_id = SANDBOX_UBOOT_IMAGE_GUID,
.fw_name = u"SANDBOX-UBOOT",
.image_index = 1,
},
{
-   .image_type_id = SANDBOX_UBOOT_ENV_IMAGE_GUID,
.fw_name = u"SANDBOX-UBOOT-ENV",
.image_index = 2,
},
 #elif defined(CONFIG_EFI_CAPSULE_FIRMWARE_FIT)
{
-   .image_type_id = SANDBOX_FIT_IMAGE_GUID,
.fw_name = u"SANDBOX-FIT",
.image_index = 1,
},
 #endif
diff --git a/include/sandbox_efi_capsule.h b/include/sandbox_efi_capsule.h
index 3e288e8a84a2..84d45ec5cfd5 100644
--- a/include/sandbox_efi_capsule.h
+++ b/include/sandbox_efi_capsule.h
@@ -5,11 +5,11 @@
 
 #if !defined(_SANDBOX_EFI_CAPSULE_H_)
 #define _SANDBOX_EFI_CAPSULE_H_
 
-#define SANDBOX_UBOOT_IMAGE_GUID   "09d7cf52-0720-4710-91d1-08469b7fe9c8"
-#define SANDBOX_UBOOT_ENV_IMAGE_GUID   "5a7021f5-fef2-48b4-aaba-832e777418c0"
-#define SANDBOX_FIT_IMAGE_GUID "3673b45d-6a7c-46f3-9e60-adabb03f7937"
+#define SANDBOX_UBOOT_IMAGE_GUID   "985f2937-7c2e-5e9a-8a5e-8e063312964b"
+#define SANDBOX_UBOOT_ENV_IMAGE_GUID   "9e339473-c2eb-530a-a69b-0cd6bbbed40e"
+#define SANDBOX_FIT_IMAGE_GUID "46610520-469e-59dc-a8dd-c11832b877ea"
 #define SANDBOX_INCORRECT_GUID "058b7d83-50d5-4c47-a195-60d86ad341c4"
 
 #define UBOOT_FIT_IMAGE"u-boot_bin_env.itb"
 
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py 
b/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py
index 11bcdc2bb293..a726c71c1138 100644
--- a/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_fit.py
@@ -146,9 +146,9 @@ class TestEfiCapsuleFirmwareFit():
 verify_content(u_boot_console, '10', 'u-boot:Old')
 verify_content(u_boot_console, '15', 'u-boot-env:Old')
 else:
 # ensure that SANDBOX_UBOOT_IMAGE_GUID is in the ESRT.
-assert '3673B45D-6A7C-46F3-9E60-ADABB03F7937' in 
''.join(output)
+assert '985F2937-7C2E-5E9A-8A5E-8E063312964B' in 
''.join(output)
 assert 'ESRT: fw_version=5' in ''.join(output)
 assert 'ESRT: lowest_supported_fw_version=3' in ''.join(output)
 
 verify_content(u_boot_console, '10', 'u-boot:New')
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_raw.py 
b/test/py/tests/test_efi_capsule/test_capsule_firmware_raw.py
index f3a2dff5c2c8..8a790405c7c4 100644
--- a/test/py/tests/test_efi_capsule/test_capsule_firmware_raw.py
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_raw.py
@@ -144,12 +144,12 @@ class TestEfiCapsuleFirmwareRaw:
 'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x10 
0x5;u-boot-env raw 0x15 0x20"',
 'efidebug capsule esrt'])
 
 # ensure that SANDBOX_UBOOT_ENV_IMAGE_GUID is in the ESRT.
-assert '5A7021F5-FEF2-48B4-AABA-832E777418C0' in ''.join(output)
+assert '9E339473-C2EB-530A-A69B-0C

[PATCH v5 04/11] doc: uefi: document dynamic UUID generation

2024-07-19 Thread Caleb Connolly
Document how platforms can generate GUIDs at runtime rather than
maintaining a list of UUIDs per-board.

Reviewed-by: Ilias Apalodimas 
Signed-off-by: Caleb Connolly 
---
 doc/develop/uefi/uefi.rst | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
index d450b12bf801..b284736cf6c2 100644
--- a/doc/develop/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -448,8 +448,35 @@ the location of the firmware updates is not a very secure
 practice. Getting this information from the firmware itself is more
 secure, assuming the firmware has been verified by a previous stage
 boot loader.
 
+Dynamic FWU GUIDs
+*
+
+The image_type_id contains a GUID value which is specific to the image
+and board being updated, that is to say it should uniquely identify the
+board model (and revision if relevant) and image pair. Traditionally,
+these GUIDs are generated manually and hardcoded on a per-board basis,
+however this scheme makes it difficult to scale up to support many
+boards.
+
+To address this, v5 GUIDs can be used to generate board-specific GUIDs
+at runtime, based on the board's devicetree root compatible 
+(e.g. "qcom,qrb5165-rb5").
+
+These strings are combined with the fw_image name to generate GUIDs for
+each image. Support for dynamic UUIDs can be enabled by generating a new
+namespace UUID and setting EFI_CAPSULE_NAMESPACE_GUID to it. Dynamic GUID
+generation is only enabled if the image_type_id property is unset for your
+firmware images, this is to avoid breaking existing boards with hardcoded
+GUIDs.
+
+The mkeficapsule tool can be used to determine the GUIDs for a particular
+board and image. It can be found in the tools directory.
+
+Firmware update images
+**
+
 The firmware images structure defines the GUID values, image index
 values and the name of the images that are to be updated through
 the capsule update feature. These values are to be defined as part of
 an array. These GUID values would be used by the Firmware Management

-- 
2.45.2



[PATCH v5 03/11] efi: add a helper to generate dynamic UUIDs

2024-07-19 Thread Caleb Connolly
Introduce a new helper efi_capsule_update_info_gen_ids() which populates
the capsule update fw images image_type_id field. This allows for
determinstic UUIDs to be used that can scale to a large number of
different boards and board variants without the need to maintain a big
list.

We call this from efi_fill_image_desc_array() to populate the UUIDs
lazily on-demand.

Signed-off-by: Caleb Connolly 
---
 lib/efi_loader/Kconfig| 12 ++
 lib/efi_loader/efi_capsule.c  |  1 +
 lib/efi_loader/efi_firmware.c | 52 +++
 3 files changed, 65 insertions(+)

diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 2fb24d7af9a4..4735f877c709 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -235,8 +235,20 @@ config EFI_CAPSULE_ON_DISK_EARLY
  If this option is enabled, capsules will be enforced to be
  executed as part of U-Boot initialisation so that they will
  surely take place whatever is set to distro_bootcmd.
 
+config EFI_CAPSULE_NAMESPACE_GUID
+   string "Namespace for dynamic capsule GUIDs"
+   # v4 UUID as a default for upstream U-Boot boards
+   default "8c9f137e-91dc-427b-b2d6-b420faebaf2a"
+   depends on EFI_HAVE_CAPSULE_SUPPORT
+   help
+ Define the namespace or "salt" GUID used to generate the per-image
+ GUIDs. This should be a GUID in the standard 8-4-4-4-12 format.
+
+ Device vendors are expected to generate their own namespace GUID
+ to avoid conflicts with upstream/community images.
+
 config EFI_CAPSULE_FIRMWARE
bool
 
 config EFI_CAPSULE_FIRMWARE_MANAGEMENT
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 635088f25a13..f3a2388506cc 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -19,8 +19,9 @@
 #include 
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
 #include 
diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c
index ba5aba098c0f..81d060b47a34 100644
--- a/lib/efi_loader/efi_firmware.c
+++ b/lib/efi_loader/efi_firmware.c
@@ -244,8 +244,57 @@ void efi_firmware_fill_version_info(struct 
efi_firmware_image_descriptor *image_
 
free(var_state);
 }
 
+/**
+ * efi_capsule_update_info_gen_ids - generate GUIDs for the images
+ *
+ * Generate the image_type_id for each image in the update_info.images array
+ * using the first compatible from the device tree and a salt
+ * UUID defined at build time.
+ *
+ * Returns:status code
+ */
+static efi_status_t efi_capsule_update_info_gen_ids(void)
+{
+   int ret, i;
+   struct uuid namespace;
+   const char *compatible; /* Full array including null bytes */
+   struct efi_fw_image *fw_array;
+
+   fw_array = update_info.images;
+   /* Check if we need to run (there are images and we didn't already 
generate their IDs) */
+   if (!update_info.num_images ||
+   memchr_inv(_array[0].image_type_id, 0, 
sizeof(fw_array[0].image_type_id)))
+   return EFI_SUCCESS;
+
+   ret = uuid_str_to_bin(CONFIG_EFI_CAPSULE_NAMESPACE_GUID,
+   (unsigned char *), UUID_STR_FORMAT_GUID);
+   if (ret) {
+   log_debug("%s: EFI_CAPSULE_NAMESPACE_GUID is invalid: %d\n", 
__func__, ret);
+   return EFI_UNSUPPORTED;
+   }
+
+   compatible = ofnode_read_string(ofnode_root(), "compatible");
+   if (!compatible) {
+   log_debug("%s: model or compatible not defined\n", __func__);
+   return EFI_UNSUPPORTED;
+   }
+
+   for (i = 0; i < update_info.num_images; i++) {
+   gen_v5_guid(,
+   _array[i].image_type_id,
+   compatible, strlen(compatible),
+   fw_array[i].fw_name, 
u16_strlen(fw_array[i].fw_name) * sizeof(uint16_t),
+   NULL);
+
+   log_debug("Image %ls UUID %pUl\n", fw_array[i].fw_name,
+ _array[i].image_type_id);
+   }
+
+   return EFI_SUCCESS;
+}
+
 /**
  * efi_fill_image_desc_array - populate image descriptor array
  * @image_info_size:   Size of @image_info
  * @image_info:Image information
@@ -282,8 +331,11 @@ static efi_status_t efi_fill_image_desc_array(
return EFI_BUFFER_TOO_SMALL;
}
*image_info_size = total_size;
 
+   if (efi_capsule_update_info_gen_ids() != EFI_SUCCESS)
+   return EFI_UNSUPPORTED;
+
fw_array = update_info.images;
*descriptor_count = update_info.num_images;
*descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
*descriptor_size = sizeof(*image_info);

-- 
2.45.2



[PATCH v5 02/11] lib: uuid: add UUID v5 support

2024-07-19 Thread Caleb Connolly
Add support for generating version 5 UUIDs, these are determistic and work
by hashing a "namespace" UUID together with some unique data. One intended
usecase is to allow for dynamically generate payload UUIDs for UEFI
capsule updates, so that supported boards can have their own UUIDs
without needing to hardcode them.

In addition, move the common bit twiddling code from gen_ran_uuid into a
separate function and rewrite it not to use clrsetbits (which is not
available when building as part of host tools).

Tests for this are added in an upcoming patch.

Signed-off-by: Caleb Connolly 
---
 include/uuid.h | 17 +++--
 lib/Kconfig|  1 +
 lib/uuid.c | 58 +++---
 3 files changed, 67 insertions(+), 9 deletions(-)

diff --git a/include/uuid.h b/include/uuid.h
index f5a941250f48..1f4fa103b5e9 100644
--- a/include/uuid.h
+++ b/include/uuid.h
@@ -10,8 +10,9 @@
 #ifndef __UUID_H__
 #define __UUID_H__
 
 #include 
+#include 
 
 /*
  * UUID - Universally Unique IDentifier - 128 bits unique number.
  *There are 5 versions and one variant of UUID defined by RFC4122
@@ -45,10 +46,10 @@
  * where x is a hexadecimal character. Fields are separated by '-'s.
  * When converting to a binary UUID, le means the field should be converted
  * to little endian and be means it should be converted to big endian.
  *
- * UUID is also used as GUID (Globally Unique Identifier) with the same binary
- * format but it differs in string format like below.
+ * UUID is also used as GUID (Globally Unique Identifier) with the same format
+ * but with some fields stored in little endian.
  *
  * GUID:
  * 0914   19   24
  * ----
@@ -142,8 +143,20 @@ void gen_rand_uuid(unsigned char *uuid_bin);
  * @param  - uuid output type: UUID - 0, GUID - 1
  */
 void gen_rand_uuid_str(char *uuid_str, int str_format);
 
+struct efi_guid;
+
+/**
+ * gen_v5_guid() - generate little endian v5 GUID from namespace and other 
seed data.
+ *
+ * @namespace:   pointer to UUID namespace salt
+ * @guid:pointer to allocated GUID output
+ * @...: NULL terminated list of seed data as pairs of pointers
+ *   to data and their lengths
+ */
+void gen_v5_guid(const struct uuid *namespace, struct efi_guid *guid, ...);
+
 /**
  * uuid_str_to_le_bin() - Convert string UUID to little endian binary data.
  * @uuid_str:  pointer to UUID string
  * @uuid_bin:  pointer to allocated array for little endian output [16B]
diff --git a/lib/Kconfig b/lib/Kconfig
index 2059219a1207..5a48c016d2c5 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -72,8 +72,9 @@ config HAVE_PRIVATE_LIBGCC
bool
 
 config LIB_UUID
bool
+   select SHA1
 
 config RANDOM_UUID
bool "GPT Random UUID generation"
select LIB_UUID
diff --git a/lib/uuid.c b/lib/uuid.c
index dfa2320ba267..7d0a8273d157 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -21,8 +21,9 @@
 #include 
 #include 
 #include 
 #include 
+#include 
 
 int uuid_str_valid(const char *uuid)
 {
int i, valid;
@@ -368,8 +369,57 @@ void uuid_bin_to_str(const unsigned char *uuid_bin, char 
*uuid_str,
}
}
 }
 
+static void configure_uuid(struct uuid *uuid, unsigned char version)
+{
+   uint16_t tmp;
+
+   /* Configure variant/version bits */
+   tmp = be16_to_cpu(uuid->time_hi_and_version);
+   tmp = (tmp & ~UUID_VERSION_MASK) | (version << UUID_VERSION_SHIFT);
+   uuid->time_hi_and_version = cpu_to_be16(tmp);
+
+   uuid->clock_seq_hi_and_reserved &= ~UUID_VARIANT_MASK;
+   uuid->clock_seq_hi_and_reserved |= (UUID_VARIANT << UUID_VARIANT_SHIFT);
+}
+
+void gen_v5_guid(const struct uuid *namespace, struct efi_guid *guid, ...)
+{
+   sha1_context ctx;
+   va_list args;
+   const uint8_t *data;
+   uint32_t *tmp32;
+   uint16_t *tmp16;
+   uint8_t hash[SHA1_SUM_LEN];
+
+   sha1_starts();
+   /* Hash the namespace UUID as salt */
+   sha1_update(, (unsigned char *)namespace, UUID_BIN_LEN);
+   va_start(args, guid);
+
+   while ((data = va_arg(args, const uint8_t *))) {
+   unsigned int len = va_arg(args, size_t);
+   sha1_update(, data, len);
+   }
+
+   va_end(args);
+   sha1_finish(, hash);
+
+   /* Truncate the hash into output UUID, it is already big endian */
+   memcpy(guid, hash, sizeof(*guid));
+
+   configure_uuid((struct uuid *)guid, 5);
+
+   /* Make little endian */
+   tmp32 = (uint32_t *)>b[0];
+   *tmp32 = be32_to_cpu(*tmp32);
+   tmp16 = (uint16_t *)>b[4];
+   *tmp16 = be16_to_cpu(*tmp16);
+   tmp16 = (uint16_t *)>b[6];
+   *tmp16 = be16_to_cpu(*tmp16);
+}
+
 #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID)
 void gen_rand_uuid(unsigned char *uuid_bin)
 {
u32 ptr[4];
@@ -394,15 +444,9 @@ void gen_rand_uui

[PATCH v5 01/11] efi: define struct efi_guid

2024-07-19 Thread Caleb Connolly
This let's us forward declare efi_guid_t in the UUID code without
pulling in efi.h

Signed-off-by: Caleb Connolly 
---
 include/efi.h  | 2 +-
 tools/eficapsule.h | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/efi.h b/include/efi.h
index c3c4b93f860a..b92c961a2afd 100644
--- a/include/efi.h
+++ b/include/efi.h
@@ -73,9 +73,9 @@ struct efi_device_path {
  * EDK2 reference implementation both define EFI_GUID as
  * struct { u32 a; u16; b; u16 c; u8 d[8]; }; which is 4-byte
  * aligned.
  */
-typedef struct {
+typedef struct efi_guid {
u8 b[16];
 } efi_guid_t __attribute__((aligned(4)));
 
 #define EFI_BITS_PER_LONG  (sizeof(long) * 8)
diff --git a/tools/eficapsule.h b/tools/eficapsule.h
index 6efd07d2eb6b..97d077536d5b 100644
--- a/tools/eficapsule.h
+++ b/tools/eficapsule.h
@@ -23,9 +23,9 @@
 #endif
 
 #define ARRAY_SIZE(x)  (sizeof(x) / sizeof((x)[0]))
 
-typedef struct {
+typedef struct efi_guid {
uint8_t b[16];
 } efi_guid_t __aligned(8);
 
 #define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \

-- 
2.45.2



[PATCH v5 00/11] efi: CapsuleUpdate: support for dynamic UUIDs

2024-07-19 Thread Caleb Connolly
As more boards adopt support for the EFI CapsuleUpdate mechanism, there
is a growing issue of being able to target updates to them properly. The
current mechanism of hardcoding UUIDs for each board at compile time is
unsustainable, and maintaining lists of GUIDs is similarly cumbersome.

In this series, I propose that we adopt v5 GUIDs, these are generated by
using a well-known salt GUID as well as board specific information the
DT root compatible string, these are hashed together and the result is
truncated to form a new UUID.

The well-known salt GUID can be specific to the architecture (SoC
vendor), or OEM. It is defined in the board defconfig so that vendors
can easily bring their own.

Specifically, the following fields are used to generate a GUID for a
particular fw_image:

* namespace salt
* board compatible (usually the first entry in the dt root compatible
  array).
* fw_image name (the string identifying the specific image, especially
  relevant for board that can update multiple images).

== Usage ==

Boards can enable dynamic UUID support by simply not setting the
efi_fw_image image_type_id property. Vendors may also wish to set a
custom namespace GUID (by setting CONFIG_EFI_CAPSULE_NAMESPACE_GUID).

== Limitations ==

* Changing GUIDs

The primary limitation with this approach is that if any of the source
fields change, so will the GUID for the board. It is therefore pretty
important to ensure that GUID changes are caught during development.

* Supporting multiple boards with a single image

This now requires having an entry with the GUID for every board which
might lead to larger UpdateCapsule images.

== Tooling ==

The mkeficapsule command is updated to add a new guidgen subcommand,
this can generate GUIDs that match those the board would generate at
runtime. It accepts an optional namespace GUID (if the default isn't
used), a path to the board DTB, and a list of firmware image names.

This series follows a related discussion started by Ilias:
https://lore.kernel.org/u-boot/cac_iwjjnha4gmf897mqyzndbgjfg8k4kwgstxwuy72wkyli...@mail.gmail.com/

CI run for this series: 
https://source.denx.de/u-boot/custodians/u-boot-snapdragon/-/pipelines/21419

---
Changes in v5:
- Clean up mkeficapsule genguid patch
- Add explicit tests validating the GUID type bits
- Link to v4: 
https://lore.kernel.org/r/20240702-b4-dynamic-uuid-v4-0-a00c82d1f...@linaro.org

Changes in v4:
- Make UUID v5 support always enabled rather than being optional.
- Fix endianness issues (thanks Vincent and Ilias)
- Merge genguid tool into mkeficapsule.
-   And move mkeficapsule over to using U-Boot's UUID code rather
than libuuid.
- Provide a default namespace UUID for all U-Boot boards.
- Link to v3: 
https://lore.kernel.org/r/20240531-b4-dynamic-uuid-v3-0-ca4a4865d...@linaro.org

Changes in v3:
- Add manpage for genguid
- Add dedicated CONFIG_TOOLS_GENGUID option
- Minor code fixes addressing v2 feedback
- Link to v2: 
https://lore.kernel.org/r/20240529-b4-dynamic-uuid-v2-0-c26f31057...@linaro.org

Changes in v2:
- Move namespace UUID to be defined in defconfig
- Add tests and tooling
- Only use the first board compatible to generate UUID.
- Link to v1: 
https://lore.kernel.org/r/20240426-b4-dynamic-uuid-v1-0-e8154e00e...@linaro.org

---
Caleb Connolly (11):
  efi: define struct efi_guid
  lib: uuid: add UUID v5 support
  efi: add a helper to generate dynamic UUIDs
  doc: uefi: document dynamic UUID generation
  sandbox: switch to dynamic UUIDs
  lib: uuid: supporting building as part of host tools
  include: export uuid.h
  tools: mkeficapsule: use u-boot UUID library
  tools: mkeficapsule: support generating dynamic GUIDs
  test: lib/uuid: add unit tests for dynamic UUIDs
  test: lib/uuid: add tests for UUID version/variant bits

 arch/arm/mach-rockchip/board.c |   2 +-
 board/cobra5272/flash.c|   2 +-
 board/gardena/smart-gateway-mt7688/board.c |   2 +-
 board/sandbox/sandbox.c|  16 --
 board/socrates/socrates.c  |   2 +-
 board/xilinx/common/board.c|   2 +-
 cmd/efi.c  |   2 +-
 cmd/efi_common.c   |   2 +-
 cmd/flash.c|   2 +-
 cmd/gpt.c  |   2 +-
 cmd/nvedit_efi.c   |   2 +-
 cmd/x86/hob.c  |   2 +-
 common/flash.c |   2 +-
 disk/part_efi.c|   2 +-
 doc/develop/uefi/uefi.rst  |  27 +++
 doc/mkeficapsule.1 |  23 +++
 drivers/firmware/arm-ffa/arm-ffa-uclass.c  |   2 +-
 env/sf.c   |   2 +-
 fs/btrfs/btrfs.c   |   2 +-
 fs

Re: [PATCH v6 06/24] soc: qcom: cmd-db: adjust probe for U-Boot

2024-07-16 Thread Caleb Connolly




On 16/07/2024 09:04, Simon Glass wrote:

Hi Caleb,

On Mon, 15 Jul 2024 at 22:42, Caleb Connolly  wrote:




On 15/07/2024 13:39, Simon Glass wrote:

On Mon, 15 Jul 2024 at 11:08, Caleb Connolly  wrote:


Integrate cmd-db into the U-Boot driver model.

This is just a wrapper around an in-memory database, so we just need to
get the address and validate that cmd-db is there.

Since cmd_db_header will be stored in the .data section we can skip
bind if it's already set.

Signed-off-by: Caleb Connolly 
---
To: Simon Glass 
---
   drivers/soc/qcom/cmd-db.c | 72 
+++
   include/soc/qcom/cmd-db.h |  3 --
   2 files changed, 23 insertions(+), 52 deletions(-)



Reviewed-by: Simon Glass 


Thanks


BTW, this is a MISC driver. Does it implement the read() operation?


No, the API (as defined in the header file) takes a string and returns a
database entry. cmd-db users don't have an easily available handle to
the node / udevice regardless.


OK. The closest thing might be UCLASS_SYSINFO, but it is designed for
inside U-Boot and uses an int instead of a string for lookup.


Right, I don't think we'll be able to find a more optimum solution here.


Could you use the devicetree for this information? What sort of info is it?


It maps resource names (e.g. "ldoa1" - the LDO1 regulator on PMIC A) to 
the address of the resource on the RPMh co-processor.


We need to support existing (upstream) devicetree, since this has 
already been around for many years.


Regards,
Simon


--
// Caleb (they/them)


Re: [PATCH v6 06/24] soc: qcom: cmd-db: adjust probe for U-Boot

2024-07-15 Thread Caleb Connolly




On 15/07/2024 13:39, Simon Glass wrote:

On Mon, 15 Jul 2024 at 11:08, Caleb Connolly  wrote:


Integrate cmd-db into the U-Boot driver model.

This is just a wrapper around an in-memory database, so we just need to
get the address and validate that cmd-db is there.

Since cmd_db_header will be stored in the .data section we can skip
bind if it's already set.

Signed-off-by: Caleb Connolly 
---
To: Simon Glass 
---
  drivers/soc/qcom/cmd-db.c | 72 +++
  include/soc/qcom/cmd-db.h |  3 --
  2 files changed, 23 insertions(+), 52 deletions(-)



Reviewed-by: Simon Glass 


Thanks


BTW, this is a MISC driver. Does it implement the read() operation?


No, the API (as defined in the header file) takes a string and returns a 
database entry. cmd-db users don't have an easily available handle to 
the node / udevice regardless.


--
// Caleb (they/them)


[PATCH v6 24/24] qcom_defconfig: enable rpmh regulators

2024-07-15 Thread Caleb Connolly
Enable RPMh, cmd-db, and RPMh regulators. Additionally enable
CMD_REGULATOR for debugging.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 configs/qcom_defconfig | 5 +
 1 file changed, 5 insertions(+)

diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index ac5ffe772ade..1cbad9db72eb 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -35,8 +35,9 @@ CONFIG_CMD_UFS=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_CAT=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_LOG=y
 CONFIG_OF_LIVE=y
 CONFIG_BUTTON_QCOM_PMIC=y
 CONFIG_CLK=y
@@ -90,11 +91,15 @@ CONFIG_PINCTRL_QCOM_SM8650=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_QCOM=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_QCOM_RPMH=y
 CONFIG_SCSI=y
 CONFIG_MSM_SERIAL=y
 CONFIG_MSM_GENI_SERIAL=y
+CONFIG_SOC_QCOM=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_QCOM_RPMH=y
 CONFIG_SPMI_MSM=y
 CONFIG_SYSINFO=y
 CONFIG_SYSINFO_SMBIOS=y
 CONFIG_USB=y

-- 
2.45.2



[PATCH v6 23/24] power: regulator: qcom-rpmh-regulator: add build infra

2024-07-15 Thread Caleb Connolly
Add Kconfig and Makefile entries for this driver now that it can build
for U-Boot.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/Kconfig  | 8 
 drivers/power/regulator/Makefile | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 102ec7bc5f89..bc061c20d75e 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -215,8 +215,16 @@ config DM_REGULATOR_GPIO
This config enables implementation of driver-model regulator uclass
features for gpio regulators. The driver implements get/set for
voltage value.
 
+config DM_REGULATOR_QCOM_RPMH
+   bool "Enable driver model for Qualcomm RPMh regulator"
+   depends on DM_REGULATOR && QCOM_RPMH
+   ---help---
+ Enable support for the Qualcomm RPMh regulator. The driver
+ implements get/set api for a limited set of regulators used
+ by u-boot.
+
 config SPL_DM_REGULATOR_GPIO
bool "Enable Driver Model for GPIO REGULATOR in SPL"
depends on DM_REGULATOR_GPIO && SPL_GPIO
select SPL_DM_REGULATOR_COMMON
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index f79932d83307..56a527612b74 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -20,8 +20,9 @@ obj-$(CONFIG_$(SPL_)REGULATOR_PWM) += pwm_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_COMMON) += regulator_common.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
+obj-$(CONFIG_DM_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
 obj-$(CONFIG_$(SPL_TPL_)REGULATOR_RK8XX) += rk8xx.o
 obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o

-- 
2.45.2



[PATCH v6 22/24] power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot

2024-07-15 Thread Caleb Connolly
Refactor initialization to use U-Boot's driver model and API.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 136 +++---
 1 file changed, 102 insertions(+), 34 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index b716b380c148..06fd3f31956f 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -411,66 +411,134 @@ static const struct rpmh_vreg_init_data 
pm8150l_vreg_data[] = {
RPMH_VREG("ldo11",  "ldo%s11", _pldo,  "vdd-l7-l11"),
{}
 };
 
-static int rpmh_regulator_probe(struct platform_device *pdev)
+/* probe an individual regulator */
+static int rpmh_regulator_probe(struct udevice *dev)
 {
-   struct device *dev = >dev;
-   const struct rpmh_vreg_init_data *vreg_data;
-   struct device_node *node;
-   struct rpmh_vreg *vreg;
-   const char *pmic_id;
-   int ret;
+   const struct rpmh_vreg_init_data *init_data;
+   struct rpmh_vreg *priv;
+   struct dm_regulator_uclass_plat *plat_data;
 
-   vreg_data = of_device_get_match_data(dev);
-   if (!vreg_data)
+   init_data = (const struct rpmh_vreg_init_data 
*)dev_get_driver_data(dev);
+   priv = dev_get_priv(dev);
+   plat_data = dev_get_uclass_plat(dev);
+
+   priv->dev = dev;
+   priv->addr = cmd_db_read_addr(dev->name);
+   if (!priv->addr) {
+   dev_err(dev, "Failed to read RPMh address for %s\n", dev->name);
return -ENODEV;
-
-   ret = of_property_read_string(dev->of_node, "qcom,pmic-id", _id);
-   if (ret < 0) {
-   dev_err(dev, "qcom,pmic-id missing in DT node\n");
-   return ret;
}
 
-   for_each_available_child_of_node(dev->of_node, node) {
-   vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
-   if (!vreg) {
-   of_node_put(node);
+   priv->hw_data = init_data->hw_data;
+   priv->enabled = -EINVAL;
+   priv->uv = -ENOTRECOVERABLE;
+   if (ofnode_read_u32(dev_ofnode(dev), "regulator-initial-mode", 
>mode))
+   priv->mode = -EINVAL;
+
+   plat_data->mode = priv->hw_data->pmic_mode_map;
+   plat_data->mode_count = priv->hw_data->n_modes;
+
+   return 0;
+}
+
+/* for non-drm, xob, or bypass regulators add additional driver definitions */
+U_BOOT_DRIVER(rpmh_regulator_drm) = {
+   .name = "rpmh_regulator_drm",
+   .id = UCLASS_REGULATOR,
+   .probe = rpmh_regulator_probe,
+   .priv_auto = sizeof(struct rpmh_vreg),
+   .ops = _regulator_vrm_drms_ops,
+};
+
+/* This driver intentionally only supports a subset of the available 
regulators.
+ * This function checks to see if a given regulator node in DT matches a 
regulator
+ * defined in the driver.
+ */
+static const struct rpmh_vreg_init_data *
+vreg_get_init_data(const struct rpmh_vreg_init_data *init_data, ofnode node)
+{
+   const struct rpmh_vreg_init_data *data;
+
+   for (data = init_data; data->name; data++) {
+   if (!strcmp(data->name, ofnode_get_name(node)))
+   return data;
+   }
+
+   return NULL;
+}
+
+static int rpmh_regulators_bind(struct udevice *dev)
+{
+   const struct rpmh_vreg_init_data *init_data, *data;
+   const char *pmic_id;
+   char *name;
+   struct driver *drv;
+   ofnode node;
+   int ret;
+   size_t namelen;
+
+   init_data = (const struct rpmh_vreg_init_data 
*)dev_get_driver_data(dev);
+   if (!init_data) {
+   dev_err(dev, "No RPMh regulator init data\n");
+   return -ENODEV;
+   }
+
+   pmic_id = ofnode_read_string(dev_ofnode(dev), "qcom,pmic-id");
+   if (!pmic_id) {
+   dev_err(dev, "No PMIC ID\n");
+   return -ENODEV;
+   }
+
+   drv = lists_driver_lookup_name("rpmh_regulator_drm");
+
+   ofnode_for_each_subnode(node, dev_ofnode(dev)) {
+   data = vreg_get_init_data(init_data, node);
+   if (!data)
+   continue;
+
+   /* %s is replaced with pmic_id, so subtract 2, then add 1 for 
the null terminator */
+   namelen = strlen(data->resource_name) + strlen(pmic_id) - 1;
+   name = devm_kzalloc(dev, namelen, GFP_KERNEL);
+   ret = snprintf(name, namelen, data->resource_name, pmic_id);
+   if (ret < 0 || ret >= namelen) {
+   dev_err(dev, "Failed to create RPMh regulator name\n");
return -ENOMEM;
}
 
-   ret = rpmh_regulator_init_vreg(vreg, dev, node,

[PATCH v6 20/24] power: regulator: qcom-rpmh-regulator: remove unused regulators

2024-07-15 Thread Caleb Connolly
Initially just include the few regulators needed for the RB5 board.
Others can be added back as-needed.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 1281 -
 1 file changed, 1281 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 089623f3a2b9..2a8e8f9ac444 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -338,68 +338,8 @@ static unsigned int rpmh_regulator_vrm_get_mode(struct 
regulator_dev *rdev)
 
return vreg->mode;
 }
 
-/**
- * rpmh_regulator_vrm_get_optimum_mode() - get the mode based on the  load
- * @rdev:  Regulator device pointer for the rpmh-regulator
- * @input_uV:  Input voltage
- * @output_uV: Output voltage
- * @load_uA:   Aggregated load current in microamps
- *
- * This function is used in the regulator_ops for VRM type RPMh regulator
- * devices.
- *
- * Return: 0 on success, errno on failure
- */
-static unsigned int rpmh_regulator_vrm_get_optimum_mode(
-   struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-
-   if (load_uA >= vreg->hw_data->hpm_min_load_uA)
-   return REGULATOR_MODE_NORMAL;
-   else
-   return REGULATOR_MODE_IDLE;
-}
-
-static int rpmh_regulator_vrm_set_bypass(struct regulator_dev *rdev,
-   bool enable)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-   int ret;
-
-   if (vreg->bypassed == enable)
-   return 0;
-
-   ret = rpmh_regulator_vrm_set_mode_bypass(vreg, vreg->mode, enable);
-   if (!ret)
-   vreg->bypassed = enable;
-
-   return ret;
-}
-
-static int rpmh_regulator_vrm_get_bypass(struct regulator_dev *rdev,
-   bool *enable)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-
-   *enable = vreg->bypassed;
-
-   return 0;
-}
-
-static const struct regulator_ops rpmh_regulator_vrm_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-   .set_voltage_sel= rpmh_regulator_vrm_set_voltage_sel,
-   .get_voltage_sel= rpmh_regulator_vrm_get_voltage_sel,
-   .list_voltage   = regulator_list_voltage_linear_range,
-   .set_mode   = rpmh_regulator_vrm_set_mode,
-   .get_mode   = rpmh_regulator_vrm_get_mode,
-};
-
 static const struct regulator_ops rpmh_regulator_vrm_drms_ops = {
.enable = rpmh_regulator_enable,
.disable= rpmh_regulator_disable,
.is_enabled = rpmh_regulator_is_enabled,
@@ -410,331 +350,8 @@ static const struct regulator_ops 
rpmh_regulator_vrm_drms_ops = {
.get_mode   = rpmh_regulator_vrm_get_mode,
.get_optimum_mode   = rpmh_regulator_vrm_get_optimum_mode,
 };
 
-static const struct regulator_ops rpmh_regulator_vrm_bypass_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-   .set_voltage_sel= rpmh_regulator_vrm_set_voltage_sel,
-   .get_voltage_sel= rpmh_regulator_vrm_get_voltage_sel,
-   .list_voltage   = regulator_list_voltage_linear_range,
-   .set_mode   = rpmh_regulator_vrm_set_mode,
-   .get_mode   = rpmh_regulator_vrm_get_mode,
-   .set_bypass = rpmh_regulator_vrm_set_bypass,
-   .get_bypass = rpmh_regulator_vrm_get_bypass,
-};
-
-static const struct regulator_ops rpmh_regulator_xob_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-};
-
-/**
- * rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator
- * @vreg:  Pointer to the individual rpmh-regulator resource
- * @dev:   Pointer to the top level rpmh-regulator PMIC 
device
- * @node:  Pointer to the individual rpmh-regulator resource
- * device node
- * @pmic_id:   String used to identify the top level rpmh-regulator
- * PMIC device on the board
- * @pmic_rpmh_data:Pointer to a null-terminated array of rpmh-regulator
- * resources defined for the top level PMIC device
- *
- * Return: 0 on success, errno on failure
- */
-static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
-   struct device_node *node, const char *pmic_id,
-

[PATCH v6 21/24] power: regulator: qcom-rpmh-regulator: port ops to U-Boot

2024-07-15 Thread Caleb Connolly
Port over the regulator ops to U-Boot's regulator API. Add back the
pmic5 mode map using U-Boot dm_regulator_mode API and adjust the
pmic5_pldo and pmic5_pldo_lv definitions. No functional changes.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 158 ++
 1 file changed, 87 insertions(+), 71 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 2a8e8f9ac444..b716b380c148 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -192,87 +192,96 @@ struct rpmh_vreg_init_data {
  *
  * Return: 0 on success, errno on failure
  */
 static int rpmh_regulator_send_request(struct rpmh_vreg *vreg,
-   struct tcs_cmd *cmd, bool wait_for_ack)
+  const struct tcs_cmd *cmd, bool 
wait_for_ack)
 {
int ret;
 
if (wait_for_ack || vreg->always_wait_for_ack)
-   ret = rpmh_write(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, 1);
+   ret = rpmh_write(vreg->dev->parent, RPMH_ACTIVE_ONLY_STATE, 
cmd, 1);
else
-   ret = rpmh_write_async(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd,
-   1);
+   ret = rpmh_write_async(vreg->dev->parent, 
RPMH_ACTIVE_ONLY_STATE, cmd, 1);
 
return ret;
 }
 
-static int _rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev,
-   unsigned int selector, bool wait_for_ack)
+static int _rpmh_regulator_vrm_set_value(struct udevice *rdev,
+int uv, bool wait_for_ack)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
struct tcs_cmd cmd = {
.addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE,
};
int ret;
+   unsigned int selector;
 
-   /* VRM voltage control register is set with voltage in millivolts. */
-   cmd.data = DIV_ROUND_UP(regulator_list_voltage_linear_range(rdev,
-   selector), 1000);
+   selector = (uv - vreg->hw_data->voltage_range.min) / 
vreg->hw_data->voltage_range.step;
+   cmd.data = DIV_ROUND_UP(vreg->hw_data->voltage_range.min +
+   selector * vreg->hw_data->voltage_range.step, 
1000);
 
ret = rpmh_regulator_send_request(vreg, , wait_for_ack);
if (!ret)
-   vreg->voltage_selector = selector;
+   vreg->uv = cmd.data * 1000;
 
return ret;
 }
 
-static int rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev,
-   unsigned int selector)
+static int rpmh_regulator_vrm_set_value(struct udevice *rdev,
+   int uv)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
+
+   debug("%s: set_value %d (current %d)\n", rdev->name, uv, vreg->uv);
 
if (vreg->enabled == -EINVAL) {
/*
 * Cache the voltage and send it later when the regulator is
 * enabled or disabled.
 */
-   vreg->voltage_selector = selector;
+   vreg->uv = uv;
return 0;
}
 
-   return _rpmh_regulator_vrm_set_voltage_sel(rdev, selector,
-   selector > vreg->voltage_selector);
+   return _rpmh_regulator_vrm_set_value(rdev, uv,
+   uv > vreg->uv);
 }
 
-static int rpmh_regulator_vrm_get_voltage_sel(struct regulator_dev *rdev)
+static int rpmh_regulator_vrm_get_value(struct udevice *rdev)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
 
-   return vreg->voltage_selector;
+   debug("%s: get_value %d\n", rdev->name, vreg->uv);
+
+   return vreg->uv;
 }
 
-static int rpmh_regulator_is_enabled(struct regulator_dev *rdev)
+static int rpmh_regulator_is_enabled(struct udevice *rdev)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
 
-   return vreg->enabled;
+   debug("%s: is_enabled %d\n", rdev->name, vreg->enabled);
+
+   return vreg->enabled > 0;
 }
 
-static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev,
-   bool enable)
+static int rpmh_regulator_set_enable_state(struct udevice *rdev,
+  bool enable)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
struct tcs_cmd cmd = {
 

[PATCH v6 16/24] power: regulator: import qcom-rpmh-regulator from Linux

2024-07-15 Thread Caleb Connolly
Import the driver from Linux 6.10-rc6.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 1709 +
 1 file changed, 1709 insertions(+)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
new file mode 100644
index ..80e304711345
--- /dev/null
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -0,0 +1,1709 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+// Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+
+/**
+ * enum rpmh_regulator_type - supported RPMh accelerator types
+ * @VRM:   RPMh VRM accelerator which supports voting on enable, voltage,
+ * and mode of LDO, SMPS, and BOB type PMIC regulators.
+ * @XOB:   RPMh XOB accelerator which supports voting on the enable state
+ * of PMIC regulators.
+ */
+enum rpmh_regulator_type {
+   VRM,
+   XOB,
+};
+
+#define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0
+#define RPMH_REGULATOR_REG_ENABLE  0x4
+#define RPMH_REGULATOR_REG_VRM_MODE0x8
+
+#define PMIC4_LDO_MODE_RETENTION   4
+#define PMIC4_LDO_MODE_LPM 5
+#define PMIC4_LDO_MODE_HPM 7
+
+#define PMIC4_SMPS_MODE_RETENTION  4
+#define PMIC4_SMPS_MODE_PFM5
+#define PMIC4_SMPS_MODE_AUTO   6
+#define PMIC4_SMPS_MODE_PWM7
+
+#define PMIC4_BOB_MODE_PASS0
+#define PMIC4_BOB_MODE_PFM 1
+#define PMIC4_BOB_MODE_AUTO2
+#define PMIC4_BOB_MODE_PWM 3
+
+#define PMIC5_LDO_MODE_RETENTION   3
+#define PMIC5_LDO_MODE_LPM 4
+#define PMIC5_LDO_MODE_HPM 7
+
+#define PMIC5_SMPS_MODE_RETENTION  3
+#define PMIC5_SMPS_MODE_PFM4
+#define PMIC5_SMPS_MODE_AUTO   6
+#define PMIC5_SMPS_MODE_PWM7
+
+#define PMIC5_BOB_MODE_PASS2
+#define PMIC5_BOB_MODE_PFM 4
+#define PMIC5_BOB_MODE_AUTO6
+#define PMIC5_BOB_MODE_PWM 7
+
+/**
+ * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
+ * @regulator_type:RPMh accelerator type used to manage this
+ * regulator
+ * @ops:   Pointer to regulator ops callback structure
+ * @voltage_ranges:The possible ranges of voltages supported by 
this
+ * PMIC regulator type
+ * @n_linear_ranges:   Number of entries in voltage_ranges
+ * @n_voltages:The number of unique voltage set points 
defined
+ * by voltage_ranges
+ * @hpm_min_load_uA:   Minimum load current in microamps that requires
+ * high power mode (HPM) operation.  This is used
+ * for LDO hardware type regulators only.
+ * @pmic_mode_map: Array indexed by regulator framework mode
+ * containing PMIC hardware modes.  Must be large
+ * enough to index all framework modes supported
+ * by this regulator hardware type.
+ * @of_map_mode:   Maps an RPMH_REGULATOR_MODE_* mode value defined
+ * in device tree to a regulator framework mode
+ */
+struct rpmh_vreg_hw_data {
+   enum rpmh_regulator_typeregulator_type;
+   const struct regulator_ops  *ops;
+   const struct linear_range   *voltage_ranges;
+   int n_linear_ranges;
+   int n_voltages;
+   int hpm_min_load_uA;
+   const int   *pmic_mode_map;
+   unsigned int  (*of_map_mode)(unsigned int mode);
+};
+
+/**
+ * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a
+ * single regulator device
+ * @dev:   Device pointer for the top-level PMIC RPMh
+ * regulator parent device.  This is used as a
+ * handle in RPMh write requests.
+ * @addr:  Base address of the regulator resource within
+ * an RPMh accelerator
+ * @rdesc: Regulator descriptor
+ * @hw_data:   PMIC regulator configuration data for

[PATCH v6 19/24] power: regulator: qcom-rpmh-regulator: adjust structs for U-Boot

2024-07-15 Thread Caleb Connolly
Switch to our linear_range helpers and remove unused/unsupported
linux-isms.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 28 +--
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index d0acee9f558e..089623f3a2b9 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -102,13 +102,12 @@ struct linear_range {
  * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
  * @regulator_type:RPMh accelerator type used to manage this
  * regulator
  * @ops:   Pointer to regulator ops callback structure
- * @voltage_ranges:The possible ranges of voltages supported by 
this
- * PMIC regulator type
- * @n_linear_ranges:   Number of entries in voltage_ranges
+ * @voltage_range: The single range of voltages supported by this
+ * PMIC regulator type
  * @n_voltages:The number of unique voltage set points 
defined
- * by voltage_ranges
+ * by voltage_range
  * @hpm_min_load_uA:   Minimum load current in microamps that requires
  * high power mode (HPM) operation.  This is used
  * for LDO hardware type regulators only.
  * @pmic_mode_map: Array indexed by regulator framework mode
@@ -119,15 +118,15 @@ struct linear_range {
  * in device tree to a regulator framework mode
  */
 struct rpmh_vreg_hw_data {
enum rpmh_regulator_typeregulator_type;
-   const struct regulator_ops  *ops;
-   const struct linear_range   *voltage_ranges;
-   int n_linear_ranges;
+   const struct dm_regulator_ops   *ops;
+   struct linear_range voltage_range;
int n_voltages;
int hpm_min_load_uA;
-   const int   *pmic_mode_map;
-   unsigned int  (*of_map_mode)(unsigned int mode);
+   struct dm_regulator_mode*pmic_mode_map;
+   int n_modes;
+   unsigned int(*of_map_mode)(unsigned int 
mode);
 };
 
 /**
  * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a
@@ -148,23 +147,22 @@ struct rpmh_vreg_hw_data {
  * not
  * @bypassed:  Boolean indicating if the regulator is in
  * bypass (pass-through) mode or not.  This is
  * only used by BOB rpmh-regulator resources.
- * @voltage_selector:  Selector used for get_voltage_sel() and
- * set_voltage_sel() callbacks
+ * @uv:Selector used for get_voltage_sel() and
+ * set_value() callbacks
  * @mode:  RPMh VRM regulator current framework mode
  */
 struct rpmh_vreg {
-   struct device   *dev;
+   struct udevice  *dev;
u32 addr;
-   struct regulator_desc   rdesc;
const struct rpmh_vreg_hw_data  *hw_data;
boolalways_wait_for_ack;
 
int enabled;
boolbypassed;
-   int voltage_selector;
-   unsigned intmode;
+   int uv;
+   int mode;
 };
 
 /**
  * struct rpmh_vreg_init_data - initialization data for an RPMh regulator

-- 
2.45.2



[PATCH v6 18/24] power: regulator: qcom-rpmh-regulator: port over lineage_range helpers

2024-07-15 Thread Caleb Connolly
Import struct linear_range() and builder macro from Linux regulator
core.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 37 +++
 1 file changed, 37 insertions(+)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 5f522de44734..d0acee9f558e 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -28,8 +28,15 @@ enum rpmh_regulator_type {
VRM,
XOB,
 };
 
+enum rpmh_regulator_mode {
+   REGULATOR_MODE_RETENTION,
+   REGULATOR_MODE_LPM,
+   REGULATOR_MODE_AUTO,
+   REGULATOR_MODE_HPM,
+};
+
 #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0
 #define RPMH_REGULATOR_REG_ENABLE  0x4
 #define RPMH_REGULATOR_REG_VRM_MODE0x8
 
@@ -60,8 +67,38 @@ enum rpmh_regulator_type {
 #define PMIC5_BOB_MODE_PFM 4
 #define PMIC5_BOB_MODE_AUTO6
 #define PMIC5_BOB_MODE_PWM 7
 
+
+/**
+ * struct linear_range - table of selector - value pairs
+ *
+ * Define a lookup-table for range of values. Intended to help when looking
+ * for a register value matching certaing physical measure (like voltage).
+ * Usable when increment of one in register always results a constant increment
+ * of the physical measure (like voltage).
+ *
+ * @min:  Lowest value in range
+ * @min_sel: Lowest selector for range
+ * @max_sel: Highest selector for range
+ * @step: Value step size
+ */
+struct linear_range {
+   unsigned int min;
+   unsigned int min_sel;
+   unsigned int max_sel;
+   unsigned int step;
+};
+
+/* Initialize struct linear_range for regulators */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)  \
+{  \
+   .min= _min_uV,  \
+   .min_sel= _min_sel, \
+   .max_sel= _max_sel, \
+   .step   = _step_uV, \
+}
+
 /**
  * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
  * @regulator_type:RPMh accelerator type used to manage this
  * regulator

-- 
2.45.2



[PATCH v6 17/24] power: regulator: qcom-rpmh-regulator: adjust headers for U-Boot

2024-07-15 Thread Caleb Connolly
Remove unused/unsupported Linux headers and add necessary U-Boot ones.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 80e304711345..5f522de44734 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -4,17 +4,14 @@
 
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
 

-- 
2.45.2



[PATCH v6 15/24] soc: qcom: add build infrastructure

2024-07-15 Thread Caleb Connolly
Add Kconfig / Makefiles to build rpmh and cmd-db drivers.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/Kconfig   |  1 +
 drivers/soc/Makefile  |  1 +
 drivers/soc/qcom/Kconfig  | 27 +++
 drivers/soc/qcom/Makefile |  4 
 4 files changed, 33 insertions(+)

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cee506fe4747..8ef408d9ba1b 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -47,8 +47,9 @@ config SOC_XILINX_VERSAL_NET
  Enable this option to select SoC device id driver for Xilinx Versal 
NET.
  This allows other drivers to verify the SoC familiy & revision using
  matching SoC attributes.
 
+source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/samsung/Kconfig"
 source "drivers/soc/ti/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ec89a053165..00e6a5ac8e2b 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,8 +2,9 @@
 #
 # Makefile for the U-Boot SOC specific device drivers.
 
 obj-$(CONFIG_SOC_AMD_VERSAL2) += soc_amd_versal2.o
+obj-$(CONFIG_SOC_QCOM) += qcom/
 obj-$(CONFIG_SOC_SAMSUNG) += samsung/
 obj-$(CONFIG_SOC_TI) += ti/
 obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
 obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
new file mode 100644
index ..4aa7833930c7
--- /dev/null
+++ b/drivers/soc/qcom/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# QCOM Soc drivers
+#
+menuconfig SOC_QCOM
+   bool "Qualcomm SOC drivers support"
+   help
+ Say Y here if you want to enable Qualcomm SOC drivers support.
+
+if SOC_QCOM
+
+config QCOM_COMMAND_DB
+   bool "Qualcomm Command DB"
+   help
+ Command DB queries shared memory by key string for shared system
+ resources. Platform drivers that require to set state of a shared
+ resource on a RPM-hardened platform must use this database to get
+ SoC specific identifier and information for the shared resources.
+
+config QCOM_RPMH
+   bool "Qualcomm RPMh support"
+   depends on QCOM_COMMAND_DB
+   help
+ Say y here to support the Qualcomm RPMh (resource peripheral manager)
+ if you need to control regulators on Qualcomm platforms, say y here.
+
+endif # SOC_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
new file mode 100644
index ..78fae8bbfa16
--- /dev/null
+++ b/drivers/soc/qcom/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_QCOM_RPMH) += rpmh-rsc.o rpmh.o

-- 
2.45.2



[PATCH v6 14/24] soc: qcom: rpmh: U-Boot API changes

2024-07-15 Thread Caleb Connolly
Fix build errors, add some debug logging.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 53 +++--
 include/soc/qcom/rpmh.h |  4 ++--
 2 files changed, 22 insertions(+), 35 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 22605e0291a1..96f14a9afdf2 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -15,27 +15,30 @@
 #include "rpmh-internal.h"
 
 #define RPMH_TIMEOUT_MSmsecs_to_jiffies(1)
 
-#define DEFINE_RPMH_MSG_ONSTACK(device, s, q, name)\
+#define DEFINE_RPMH_MSG_ONSTACK(device, s, name)   \
struct rpmh_request name = {\
.msg = {\
.state = s, \
.cmds = name.cmd,   \
.num_cmds = 0,  \
-   .wait_for_compl = true, \
},  \
.cmd = { { 0 } },   \
-   .completion = q,\
.dev = device,  \
-   .needs_free = false,\
+   .needs_free = false,\
}
 
 #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
 
-static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
+static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct udevice *dev)
 {
-   struct rsc_drv *drv = dev_get_drvdata(dev->parent);
+   struct rsc_drv *drv = (struct rsc_drv *)dev_get_priv(dev->parent);
+
+   if (!drv) {
+   log_err("BUG: no RPMh driver for %s (parent %s)\n", dev->name, 
dev->parent->name);
+   BUG();
+   }
 
return >client;
 }
 
@@ -49,36 +52,23 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct 
device *dev)
  * Cache the RPMH request and send if the state is ACTIVE_ONLY.
  * SLEEP/WAKE_ONLY requests are not sent to the controller at
  * this time. Use rpmh_flush() to send them to the controller.
  */
-static int __rpmh_write(const struct device *dev, enum rpmh_state state,
+static int __rpmh_write(const struct udevice *dev, enum rpmh_state state,
struct rpmh_request *rpm_msg)
 {
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
-   int ret = -EINVAL;
-   struct cache_req *req;
-   int i;
 
-   /* Cache the request in our store and link the payload */
-   for (i = 0; i < rpm_msg->msg.num_cmds; i++) {
-   req = cache_rpm_request(ctrlr, state, _msg->msg.cmds[i]);
-   if (IS_ERR(req))
-   return PTR_ERR(req);
+   if (state != RPMH_ACTIVE_ONLY_STATE) {
+   log_err("only ACTIVE_ONLY state supported\n");
+   return -EINVAL;
}
 
-   if (state == RPMH_ACTIVE_ONLY_STATE) {
-   ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), _msg->msg);
-   } else {
-   /* Clean up our call by spoofing tx_done */
-   ret = 0;
-   rpmh_tx_done(_msg->msg);
-   }
-
-   return ret;
+   return rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), _msg->msg);
 }
 
 static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
-   const struct tcs_cmd *cmd, u32 n)
+  const struct tcs_cmd *cmd, u32 n)
 {
if (!cmd || !n || n > MAX_RPMH_PAYLOAD)
return -EINVAL;
 
@@ -87,8 +77,10 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
req->msg.state = state;
req->msg.cmds = req->cmd;
req->msg.num_cmds = n;
 
+   debug("rpmh_msg: %d, %d cmds [first %#x/%#x]\n", state, n, cmd->addr, 
cmd->data);
+
return 0;
 }
 
 /**
@@ -100,24 +92,19 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
  * @n: The number of elements in @cmd
  *
  * May sleep. Do not call from atomic contexts.
  */
-int rpmh_write(const struct device *dev, enum rpmh_state state,
+int rpmh_write(const struct udevice *dev, enum rpmh_state state,
   const struct tcs_cmd *cmd, u32 n)
 {
-   DECLARE_COMPLETION_ONSTACK(compl);
-   DEFINE_RPMH_MSG_ONSTACK(dev, state, , rpm_msg);
+   DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg);
int ret;
 
ret = __fill_rpmh_msg(_msg, state, cmd, n);
if (ret)
return ret;
 
ret = __rpmh_write(dev, state, _msg);
-   if (ret)
-   return ret;
 
-   ret = wait_for_completion_timeout(, RPMH_TIMEOUT_MS);
-   WARN_ON(!ret);
-   return (ret > 0) ? 0 : -ETIMEDOUT;
+   return ret;
 }
 EXPORT_SYMBOL_GPL(rpmh_write);
diff --git a/include/soc/qcom/rpmh.h b

[PATCH v6 13/24] soc: qcom: rpmh: drop unused functions

2024-07-15 Thread Caleb Connolly
A lot of the features in here are only relevant when running
multi-threaded with interrupts. Drop everything except what we need to
run single-threaded with a single TCS (which is all the rpmh-rsc
framework in U-Boot supports).

Keep rpmh_write_async() for simplicity and make it wrap the regular
rpmh_write().

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 371 
 include/soc/qcom/rpmh.h |  25 +---
 2 files changed, 3 insertions(+), 393 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 03ef4106c9a6..22605e0291a1 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -31,124 +31,15 @@
}
 
 #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
 
-/**
- * struct cache_req: the request object for caching
- *
- * @addr: the address of the resource
- * @sleep_val: the sleep vote
- * @wake_val: the wake vote
- * @list: linked list obj
- */
-struct cache_req {
-   u32 addr;
-   u32 sleep_val;
-   u32 wake_val;
-   struct list_head list;
-};
-
-/**
- * struct batch_cache_req - An entry in our batch catch
- *
- * @list: linked list obj
- * @count: number of messages
- * @rpm_msgs: the messages
- */
-
-struct batch_cache_req {
-   struct list_head list;
-   int count;
-   struct rpmh_request rpm_msgs[];
-};
-
 static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
 {
struct rsc_drv *drv = dev_get_drvdata(dev->parent);
 
return >client;
 }
 
-void rpmh_tx_done(const struct tcs_request *msg)
-{
-   struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
-   msg);
-   struct completion *compl = rpm_msg->completion;
-   bool free = rpm_msg->needs_free;
-
-   if (!compl)
-   goto exit;
-
-   /* Signal the blocking thread we are done */
-   complete(compl);
-
-exit:
-   if (free)
-   kfree(rpm_msg);
-}
-
-static struct cache_req *__find_req(struct rpmh_ctrlr *ctrlr, u32 addr)
-{
-   struct cache_req *p, *req = NULL;
-
-   list_for_each_entry(p, >cache, list) {
-   if (p->addr == addr) {
-   req = p;
-   break;
-   }
-   }
-
-   return req;
-}
-
-static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr,
-  enum rpmh_state state,
-  struct tcs_cmd *cmd)
-{
-   struct cache_req *req;
-   unsigned long flags;
-   u32 old_sleep_val, old_wake_val;
-
-   spin_lock_irqsave(>cache_lock, flags);
-   req = __find_req(ctrlr, cmd->addr);
-   if (req)
-   goto existing;
-
-   req = kzalloc(sizeof(*req), GFP_ATOMIC);
-   if (!req) {
-   req = ERR_PTR(-ENOMEM);
-   goto unlock;
-   }
-
-   req->addr = cmd->addr;
-   req->sleep_val = req->wake_val = UINT_MAX;
-   list_add_tail(>list, >cache);
-
-existing:
-   old_sleep_val = req->sleep_val;
-   old_wake_val = req->wake_val;
-
-   switch (state) {
-   case RPMH_ACTIVE_ONLY_STATE:
-   case RPMH_WAKE_ONLY_STATE:
-   req->wake_val = cmd->data;
-   break;
-   case RPMH_SLEEP_STATE:
-   req->sleep_val = cmd->data;
-   break;
-   }
-
-   ctrlr->dirty |= (req->sleep_val != old_sleep_val ||
-req->wake_val != old_wake_val) &&
-req->sleep_val != UINT_MAX &&
-req->wake_val != UINT_MAX;
-
-unlock:
-   spin_unlock_irqrestore(>cache_lock, flags);
-
-   return req;
-}
-
 /**
  * __rpmh_write: Cache and send the RPMH request
  *
  * @dev: The device making the request
@@ -199,40 +90,8 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
 
return 0;
 }
 
-/**
- * rpmh_write_async: Write a set of RPMH commands
- *
- * @dev: The device making the request
- * @state: Active/sleep set
- * @cmd: The payload data
- * @n: The number of elements in payload
- *
- * Write a set of RPMH commands, the order of commands is maintained
- * and will be sent as a single shot.
- */
-int rpmh_write_async(const struct device *dev, enum rpmh_state state,
-const struct tcs_cmd *cmd, u32 n)
-{
-   struct rpmh_request *rpm_msg;
-   int ret;
-
-   rpm_msg = kzalloc(sizeof(*rpm_msg), GFP_ATOMIC);
-   if (!rpm_msg)
-   return -ENOMEM;
-   rpm_msg->needs_free = true;
-
-   ret = __fill_rpmh_msg(rpm_msg, state, cmd, n);
-   if (ret) {
-   kfree(rpm_msg);
-   return ret;
-   }
-
-   return __rpmh_write(dev, state, rpm_msg);
-}
-EXPORT_SYMBOL_GPL(rpmh_write_async);
-
 /**
  * rpmh_write: 

[PATCH v6 12/24] soc: qcom: rpmh: adjust headers for U-Boot

2024-07-15 Thread Caleb Connolly
Drop unused/unsupported Linux headers and add dm/device.h for U-Boot.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 8903ed956312..03ef4106c9a6 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -2,22 +2,14 @@
 /*
  * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  */
 
-#include 
+#include 
+#include 
 #include 
-#include 
-#include 
 #include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
 #include 
-#include 
 
 #include 
 
 #include "rpmh-internal.h"

-- 
2.45.2



[PATCH v6 11/24] soc: qcom: rpmh-rsc: remaining U-Boot API changes

2024-07-15 Thread Caleb Connolly
Minor adjustments to fix building with U-Boot and work correctly as a
synchronous driver without interrupts. RPMh is fast enough that we can
get away with just firing off requests and assuming they complete.

U-Boot behaviour changes are annotated with a "U-Boot:" comment.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-rsc.c | 78 +
 1 file changed, 29 insertions(+), 49 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 2afe5005facf..61fb2e695587 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -133,16 +133,8 @@ enum {
  *  |  ..   |
  *  +---+
  */
 
-#define USECS_TO_CYCLES(time_usecs)\
-   xloops_to_cycles((time_usecs) * 0x10C7UL)
-
-static inline unsigned long xloops_to_cycles(u64 xloops)
-{
-   return (xloops * loops_per_jiffy * HZ) >> 32;
-}
-
 static u32 rpmh_rsc_reg_offset_ver_2_7[] = {
[RSC_DRV_TCS_OFFSET]= 672,
[RSC_DRV_CMD_OFFSET]= 20,
[DRV_SOLVER_CONFIG] = 0x04,
@@ -247,37 +239,18 @@ static void write_tcs_reg_sync(const struct rsc_drv *drv, 
int reg, int tcs_id,
  */
 static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv,
 const struct tcs_request *msg)
 {
-   int type;
-   struct tcs_group *tcs;
-
-   switch (msg->state) {
-   case RPMH_ACTIVE_ONLY_STATE:
-   type = ACTIVE_TCS;
-   break;
-   case RPMH_WAKE_ONLY_STATE:
-   type = WAKE_TCS;
-   break;
-   case RPMH_SLEEP_STATE:
-   type = SLEEP_TCS;
-   break;
-   default:
+   /*
+* U-Boot: since we're single threaded and running synchronously we can
+* just always used the first active TCS.
+*/
+   if (msg->state != RPMH_ACTIVE_ONLY_STATE) {
+   log_err("WARN: only ACTIVE_ONLY state supported\n");
return ERR_PTR(-EINVAL);
}
 
-   /*
-* If we are making an active request on a RSC that does not have a
-* dedicated TCS for active state use, then re-purpose a wake TCS to
-* send active votes. This is safe because we ensure any active-only
-* transfers have finished before we use it (maybe by running from
-* the last CPU in PM code).
-*/
-   tcs = >tcs[type];
-   if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs)
-   tcs = >tcs[WAKE_TCS];
-
-   return tcs;
+   return >tcs[ACTIVE_TCS];
 }
 
 /**
  * __tcs_buffer_write() - Write to TCS hardware from a request; don't trigger.
@@ -297,11 +270,8 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
u32 cmd_enable = 0;
struct tcs_cmd *cmd;
int i, j;
 
-   /* Convert all commands to RR when the request has wait_for_compl set */
-   cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0;
-
for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) {
cmd = >cmds[i];
cmd_enable |= BIT(j);
msgid = cmd_msgid;
@@ -313,9 +283,11 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
 
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, 
msgid);
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, 
cmd->addr);
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, 
cmd->data);
-   trace_rpmh_send_msg(drv, tcs_id, msg->state, j, msgid, cmd);
+   debug("tcs(m): %d [%s] cmd(n): %d msgid: %#x addr: %#x data: 
%#x complete: %d\n",
+ tcs_id, msg->state == RPMH_ACTIVE_ONLY_STATE ? "active" : 
"?", j, msgid,
+ cmd->addr, cmd->data, cmd->wait);
}
 
cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id);
write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable);
@@ -345,34 +317,28 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
  */
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
 {
struct tcs_group *tcs;
-   int tcs_id;
-
-   might_sleep();
+   int tcs_id, i;
+   u32 addr;
 
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
 
-   spin_lock_irq(>lock);
-
-   /* Wait forever for a free tcs. It better be there eventually! */
-   wait_event_lock_irq(drv->tcs_wait,
-   (tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
-   drv->lock);
+   /* u-boot is s

[PATCH v6 10/24] soc: qcom: rpmh-rsc: adjust probe for U-Boot

2024-07-15 Thread Caleb Connolly
Rework the rpmh-rsc initialization to use U-Boot's driver model and
initialize cmd-db.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-internal.h |  14 ++---
 drivers/soc/qcom/rpmh-rsc.c  | 123 ++-
 2 files changed, 34 insertions(+), 103 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
index 12c5b8d9cf86..ac8f6c35a7a4 100644
--- a/drivers/soc/qcom/rpmh-internal.h
+++ b/drivers/soc/qcom/rpmh-internal.h
@@ -7,17 +7,18 @@
 #ifndef __RPM_INTERNAL_H__
 #define __RPM_INTERNAL_H__
 
 #include 
-#include 
 #include 
 
 #define TCS_TYPE_NR4
 #define MAX_CMDS_PER_TCS   16
 #define MAX_TCS_PER_TYPE   3
 #define MAX_TCS_NR (MAX_TCS_PER_TYPE * TCS_TYPE_NR)
 #define MAX_TCS_SLOTS  (MAX_CMDS_PER_TCS * MAX_TCS_PER_TYPE)
 
+#define USEC_PER_SEC   100UL
+
 struct rsc_drv;
 
 /**
  * struct tcs_group: group of Trigger Command Sets (TCS) to send state requests
@@ -63,10 +64,9 @@ struct tcs_group {
  */
 struct rpmh_request {
struct tcs_request msg;
struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
-   struct completion *completion;
-   const struct device *dev;
+   const struct udevice *dev;
bool needs_free;
 };
 
 /**
@@ -78,9 +78,8 @@ struct rpmh_request {
  * @batch_cache: Cache sleep and wake requests sent as batch
  */
 struct rpmh_ctrlr {
struct list_head cache;
-   spinlock_t cache_lock;
bool dirty;
struct list_head batch_cache;
 };
 
@@ -122,17 +121,12 @@ struct rsc_drv {
void __iomem *base;
void __iomem *tcs_base;
int id;
int num_tcs;
-   struct notifier_block rsc_pm;
-   struct notifier_block genpd_nb;
-   atomic_t cpus_in_pm;
struct tcs_group tcs[TCS_TYPE_NR];
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
-   spinlock_t lock;
-   wait_queue_head_t tcs_wait;
struct rpmh_ctrlr client;
-   struct device *dev;
+   struct udevice *dev;
struct rsc_ver ver;
u32 *regs;
 };
 
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 6b47c8001cac..2afe5005facf 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -385,20 +385,20 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct 
tcs_request *msg)
 
return 0;
 }
 
-static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv 
*drv)
+static int rpmh_probe_tcs_config(struct udevice *dev, struct rsc_drv *drv)
 {
struct tcs_type_config {
u32 type;
u32 n;
} tcs_cfg[TCS_TYPE_NR] = { { 0 } };
-   struct device_node *dn = pdev->dev.of_node;
+   ofnode dn = dev_ofnode(dev);
u32 config, max_tcs, ncpt, offset;
int i, ret, n, st = 0;
struct tcs_group *tcs;
 
-   ret = of_property_read_u32(dn, "qcom,tcs-offset", );
+   ret = ofnode_read_u32(dn, "qcom,tcs-offset", );
if (ret)
return ret;
drv->tcs_base = drv->base + offset;
 
@@ -410,24 +410,15 @@ static int rpmh_probe_tcs_config(struct platform_device 
*pdev, struct rsc_drv *d
 
ncpt = config & (DRV_NCPT_MASK << DRV_NCPT_SHIFT);
ncpt = ncpt >> DRV_NCPT_SHIFT;
 
-   n = of_property_count_u32_elems(dn, "qcom,tcs-config");
-   if (n != 2 * TCS_TYPE_NR)
-   return -EINVAL;
+   n = ofnode_read_u32_array(dn, "qcom,tcs-config", (u32 *)tcs_cfg, 2 * 
TCS_TYPE_NR);
+   if (n < 0) {
+   log_err("RPMh: %s: error reading qcom,tcs-config %d\n", 
dev->name, n);
+   return n;
+   }
 
for (i = 0; i < TCS_TYPE_NR; i++) {
-   ret = of_property_read_u32_index(dn, "qcom,tcs-config",
-i * 2, _cfg[i].type);
-   if (ret)
-   return ret;
-   if (tcs_cfg[i].type >= TCS_TYPE_NR)
-   return -EINVAL;
-
-   ret = of_property_read_u32_index(dn, "qcom,tcs-config",
-i * 2 + 1, _cfg[i].n);
-   if (ret)
-   return ret;
if (tcs_cfg[i].n > MAX_TCS_PER_TYPE)
return -EINVAL;
}
 
@@ -456,43 +447,28 @@ static int rpmh_probe_tcs_config(struct platform_device 
*pdev, struct rsc_drv *d
 
return 0;
 }
 
-static int rpmh_rsc_probe(struct platform_device *pdev)
+static int rpmh_rsc_probe(struct udevice *dev)
 {
-   struct device_node *dn = pdev->dev.of_node;
+   ofnode dn = dev_ofnode(dev);
struct rsc_drv *drv;
char drv_id[10] = {0};
-   int ret, irq;
-   u32 solver_config;
+   int ret;
u32 rsc_id;
 
-   /*
-* Even thoug

[PATCH v6 09/24] soc: qcom: rpmh-rsc: adjust headers for U-Boot

2024-07-15 Thread Caleb Connolly
Remove unsupported / unused Linux headers and add those needed for
U-Boot.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-rsc.c | 36 
 1 file changed, 12 insertions(+), 24 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index fc8321bf208f..6b47c8001cac 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -5,39 +5,27 @@
  */
 
 #define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME
 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
 
-#include 
-#include 
 #include 
 #include 
 
 #include "rpmh-internal.h"
 
-#define CREATE_TRACE_POINTS
-#include "trace-rpmh.h"
-
 
 #define RSC_DRV_ID 0
 
 #define MAJOR_VER_MASK 0xFF

-- 
2.45.2



[PATCH v6 08/24] soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS support

2024-07-15 Thread Caleb Connolly
Since U-Boot is single threaded, we can avoid most of the complexity
that comes with handling more than one in-flight TCS. Drop all the rpmh
code associated with multi-threading as we'll instead wait for a
response on each TCS.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-internal.h |   4 -
 drivers/soc/qcom/rpmh-rsc.c  | 562 ---
 2 files changed, 566 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
index e3cf1beff803..12c5b8d9cf86 100644
--- a/drivers/soc/qcom/rpmh-internal.h
+++ b/drivers/soc/qcom/rpmh-internal.h
@@ -139,10 +139,6 @@ struct rsc_drv {
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg);
 int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
 const struct tcs_request *msg);
 void rpmh_rsc_invalidate(struct rsc_drv *drv);
-void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv);
-
-void rpmh_tx_done(const struct tcs_request *msg);
-int rpmh_flush(struct rpmh_ctrlr *ctrlr);
 
 #endif /* __RPM_INTERNAL_H__ */
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index de86009ecd91..fc8321bf208f 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -246,49 +246,8 @@ static void write_tcs_reg_sync(const struct rsc_drv *drv, 
int reg, int tcs_id,
pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
   data, tcs_id, reg);
 }
 
-/**
- * tcs_invalidate() - Invalidate all TCSes of the given type (sleep or wake).
- * @drv:  The RSC controller.
- * @type: SLEEP_TCS or WAKE_TCS
- *
- * This will clear the "slots" variable of the given tcs_group and also
- * tell the hardware to forget about all entries.
- *
- * The caller must ensure that no other RPMH actions are happening when this
- * function is called, since otherwise the device may immediately become
- * used again even before this function exits.
- */
-static void tcs_invalidate(struct rsc_drv *drv, int type)
-{
-   int m;
-   struct tcs_group *tcs = >tcs[type];
-
-   /* Caller ensures nobody else is running so no lock */
-   if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS))
-   return;
-
-   for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++)
-   write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], m, 0);
-
-   bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
-}
-
-/**
- * rpmh_rsc_invalidate() - Invalidate sleep and wake TCSes.
- * @drv: The RSC controller.
- *
- * The caller must ensure that no other RPMH actions are happening when this
- * function is called, since otherwise the device may immediately become
- * used again even before this function exits.
- */
-void rpmh_rsc_invalidate(struct rsc_drv *drv)
-{
-   tcs_invalidate(drv, SLEEP_TCS);
-   tcs_invalidate(drv, WAKE_TCS);
-}
-
 /**
  * get_tcs_for_msg() - Get the tcs_group used to send the given message.
  * @drv: The RSC controller.
  * @msg: The message we want to send.
@@ -331,158 +290,8 @@ static struct tcs_group *get_tcs_for_msg(struct rsc_drv 
*drv,
 
return tcs;
 }
 
-/**
- * get_req_from_tcs() - Get a stashed request that was xfering on the given 
TCS.
- * @drv:The RSC controller.
- * @tcs_id: The global ID of this TCS.
- *
- * For ACTIVE_ONLY transfers we want to call back into the client when the
- * transfer finishes. To do this we need the "request" that the client
- * originally provided us. This function grabs the request that we stashed
- * when we started the transfer.
- *
- * This only makes sense for ACTIVE_ONLY transfers since those are the only
- * ones we track sending (the only ones we enable interrupts for and the only
- * ones we call back to the client for).
- *
- * Return: The stashed request.
- */
-static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv,
- int tcs_id)
-{
-   struct tcs_group *tcs;
-   int i;
-
-   for (i = 0; i < TCS_TYPE_NR; i++) {
-   tcs = >tcs[i];
-   if (tcs->mask & BIT(tcs_id))
-   return tcs->req[tcs_id - tcs->offset];
-   }
-
-   return NULL;
-}
-
-/**
- * __tcs_set_trigger() - Start xfer on a TCS or unset trigger on a borrowed TCS
- * @drv: The controller.
- * @tcs_id:  The global ID of this TCS.
- * @trigger: If true then untrigger/retrigger. If false then just untrigger.
- *
- * In the normal case we only ever call with "trigger=true" to start a
- * transfer. That will un-trigger/disable the TCS from the last transfer
- * then trigger/enable for this transfer.
- *
- * If we borrowed a wake TCS for an active-only transfer we'll also call
- * this function with "trigger=false" to just do the un-trigger/disable
- * before using the TCS for wake purposes again.
- *
- * Note that the AP is only in charge of triggering acti

[PATCH v6 07/24] soc: qcom: cmd-db: adjust for U-Boot API

2024-07-15 Thread Caleb Connolly
Keep the header pointer in the .data section so we don't initialize it
again after relocation, adjust cmd_db_get_header() to work with the
U-Boot API, and skip validating the header since all cmd-db users are
children of the rpmh-rsc and those children will only probe if cmd-db
initializes successfully.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index f707aed59adf..08736ea936ae 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -128,16 +128,12 @@ static int cmd_db_get_header(const char *id, const struct 
entry_header **eh,
 const struct rsc_hdr **rh)
 {
const struct rsc_hdr *rsc_hdr;
const struct entry_header *ent;
-   int ret, i, j;
+   int i, j;
u8 query[sizeof(ent->id)] __nonstring;
 
-   ret = cmd_db_ready();
-   if (ret)
-   return ret;
-
-   strtomem_pad(query, id, 0);
+   strncpy(query, id, sizeof(query));
 
for (i = 0; i < MAX_SLV_ID; i++) {
rsc_hdr = _db_header->header[i];
if (!rsc_hdr->slv_id)
@@ -172,8 +168,15 @@ u32 cmd_db_read_addr(const char *id)
 {
int ret;
const struct entry_header *ent;
 
+   debug("%s(%s)\n", __func__, id);
+
+   if (!cmd_db_header) {
+   log_err("%s: Command DB not initialized\n", __func__);
+   return 0;
+   }
+
ret = cmd_db_get_header(id, , NULL);
 
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
@@ -213,9 +216,9 @@ static const struct udevice_id cmd_db_ids[] = {
 
 U_BOOT_DRIVER(qcom_cmd_db) = {
.name   = "qcom_cmd_db",
.id = UCLASS_MISC,
-   .probe  = cmd_db_bind,
+   .bind   = cmd_db_bind,
.of_match   = cmd_db_ids,
 };
 
 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver");

-- 
2.45.2



[PATCH v6 06/24] soc: qcom: cmd-db: adjust probe for U-Boot

2024-07-15 Thread Caleb Connolly
Integrate cmd-db into the U-Boot driver model.

This is just a wrapper around an in-memory database, so we just need to
get the address and validate that cmd-db is there.

Since cmd_db_header will be stored in the .data section we can skip
bind if it's already set.

Signed-off-by: Caleb Connolly 
---
To: Simon Glass 
---
 drivers/soc/qcom/cmd-db.c | 72 +++
 include/soc/qcom/cmd-db.h |  3 --
 2 files changed, 23 insertions(+), 52 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index 4317310d0bcd..f707aed59adf 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -105,9 +105,9 @@ static bool cmd_db_magic_matches(const struct cmd_db_header 
*header)
 
return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
 }
 
-static struct cmd_db_header *cmd_db_header;
+static struct cmd_db_header *cmd_db_header __section(".data") = NULL;
 
 static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
 {
u16 offset = le16_to_cpu(hdr->header_offset);
@@ -123,24 +123,8 @@ rsc_offset(const struct rsc_hdr *hdr, const struct 
entry_header *ent)
 
return cmd_db_header->data + offset + loffset;
 }
 
-/**
- * cmd_db_ready - Indicates if command DB is available
- *
- * Return: 0 on success, errno otherwise
- */
-int cmd_db_ready(void)
-{
-   if (cmd_db_header == NULL)
-   return -EPROBE_DEFER;
-   else if (!cmd_db_magic_matches(cmd_db_header))
-   return -EINVAL;
-
-   return 0;
-}
-EXPORT_SYMBOL_GPL(cmd_db_ready);
-
 static int cmd_db_get_header(const char *id, const struct entry_header **eh,
 const struct rsc_hdr **rh)
 {
const struct rsc_hdr *rsc_hdr;
@@ -194,55 +178,45 @@ u32 cmd_db_read_addr(const char *id)
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
 EXPORT_SYMBOL_GPL(cmd_db_read_addr);
 
-static int cmd_db_dev_probe(struct platform_device *pdev)
+int cmd_db_bind(struct udevice *dev)
 {
-   struct reserved_mem *rmem;
-   int ret = 0;
+   void __iomem *base;
+   ofnode node;
 
-   rmem = of_reserved_mem_lookup(pdev->dev.of_node);
-   if (!rmem) {
-   dev_err(>dev, "failed to acquire memory region\n");
-   return -EINVAL;
-   }
-
-   cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
-   if (!cmd_db_header) {
-   ret = -ENOMEM;
-   cmd_db_header = NULL;
-   return ret;
+   if (cmd_db_header)
+   return 0;
+
+   node = dev_ofnode(dev);
+
+   debug("%s(%s)\n", __func__, ofnode_get_name(node));
+
+   base = (void __iomem *)ofnode_get_addr(node);
+   if ((fdt_addr_t)base == FDT_ADDR_T_NONE) {
+   log_err("%s: Failed to read base address\n", __func__);
+   return -ENOENT;
}
 
+   cmd_db_header = base;
if (!cmd_db_magic_matches(cmd_db_header)) {
-   dev_err(>dev, "Invalid Command DB Magic\n");
+   log_err("%s: Invalid Command DB Magic\n", __func__);
return -EINVAL;
}
 
-   device_set_pm_not_required(>dev);
-
return 0;
 }
 
-static const struct of_device_id cmd_db_match_table[] = {
+static const struct udevice_id cmd_db_ids[] = {
{ .compatible = "qcom,cmd-db" },
{ }
 };
-MODULE_DEVICE_TABLE(of, cmd_db_match_table);
 
-static struct platform_driver cmd_db_dev_driver = {
-   .probe  = cmd_db_dev_probe,
-   .driver = {
-  .name = "cmd-db",
-  .of_match_table = cmd_db_match_table,
-  .suppress_bind_attrs = true,
-   },
+U_BOOT_DRIVER(qcom_cmd_db) = {
+   .name   = "qcom_cmd_db",
+   .id = UCLASS_MISC,
+   .probe  = cmd_db_bind,
+   .of_match   = cmd_db_ids,
 };
 
-static int __init cmd_db_device_init(void)
-{
-   return platform_driver_register(_db_dev_driver);
-}
-core_initcall(cmd_db_device_init);
-
 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h
index 753c7923f8e5..1190f2c22cab 100644
--- a/include/soc/qcom/cmd-db.h
+++ b/include/soc/qcom/cmd-db.h
@@ -21,13 +21,10 @@ enum cmd_db_hw_type {
 
 #if IS_ENABLED(CONFIG_QCOM_COMMAND_DB)
 u32 cmd_db_read_addr(const char *resource_id);
 
-int cmd_db_ready(void);
 #else
 static inline u32 cmd_db_read_addr(const char *resource_id)
 { return 0; }
 
-static inline int cmd_db_ready(void)
-{ return -ENODEV; }
 #endif /* CONFIG_QCOM_COMMAND_DB */
 #endif /* __QCOM_COMMAND_DB_H__ */

-- 
2.45.2



[PATCH v6 05/24] soc: qcom: cmd-db: drop unused functions

2024-07-15 Thread Caleb Connolly
Due to our simpler rpmh-rsc driver and lack of debugfs, we don't need
quite a few cmd-db functions, just drop them.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 144 --
 include/soc/qcom/cmd-db.h |  15 -
 2 files changed, 159 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index b25f3549c18f..4317310d0bcd 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -194,150 +194,8 @@ u32 cmd_db_read_addr(const char *id)
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
 EXPORT_SYMBOL_GPL(cmd_db_read_addr);
 
-/**
- * cmd_db_read_aux_data() - Query command db for aux data.
- *
- *  @id: Resource to retrieve AUX Data on
- *  @len: size of data buffer returned
- *
- *  Return: pointer to data on success, error pointer otherwise
- */
-const void *cmd_db_read_aux_data(const char *id, size_t *len)
-{
-   int ret;
-   const struct entry_header *ent;
-   const struct rsc_hdr *rsc_hdr;
-
-   ret = cmd_db_get_header(id, , _hdr);
-   if (ret)
-   return ERR_PTR(ret);
-
-   if (len)
-   *len = le16_to_cpu(ent->len);
-
-   return rsc_offset(rsc_hdr, ent);
-}
-EXPORT_SYMBOL_GPL(cmd_db_read_aux_data);
-
-/**
- * cmd_db_match_resource_addr() - Compare if both Resource addresses are same
- *
- * @addr1: Resource address to compare
- * @addr2: Resource address to compare
- *
- * Return: true if two addresses refer to the same resource, false otherwise
- */
-bool cmd_db_match_resource_addr(u32 addr1, u32 addr2)
-{
-   /*
-* Each RPMh VRM accelerator resource has 3 or 4 contiguous 4-byte
-* aligned addresses associated with it. Ignore the offset to check
-* for VRM requests.
-*/
-   if (addr1 == addr2)
-   return true;
-   else if (SLAVE_ID(addr1) == CMD_DB_HW_VRM && VRM_ADDR(addr1) == 
VRM_ADDR(addr2))
-   return true;
-
-   return false;
-}
-EXPORT_SYMBOL_GPL(cmd_db_match_resource_addr);
-
-/**
- * cmd_db_read_slave_id - Get the slave ID for a given resource address
- *
- * @id: Resource id to query the DB for version
- *
- * Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error
- */
-enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
-{
-   int ret;
-   const struct entry_header *ent;
-   u32 addr;
-
-   ret = cmd_db_get_header(id, , NULL);
-   if (ret < 0)
-   return CMD_DB_HW_INVALID;
-
-   addr = le32_to_cpu(ent->addr);
-   return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
-}
-EXPORT_SYMBOL_GPL(cmd_db_read_slave_id);
-
-#ifdef CONFIG_DEBUG_FS
-static int cmd_db_debugfs_dump(struct seq_file *seq, void *p)
-{
-   int i, j;
-   const struct rsc_hdr *rsc;
-   const struct entry_header *ent;
-   const char *name;
-   u16 len, version;
-   u8 major, minor;
-
-   seq_puts(seq, "Command DB DUMP\n");
-
-   for (i = 0; i < MAX_SLV_ID; i++) {
-   rsc = _db_header->header[i];
-   if (!rsc->slv_id)
-   break;
-
-   switch (le16_to_cpu(rsc->slv_id)) {
-   case CMD_DB_HW_ARC:
-   name = "ARC";
-   break;
-   case CMD_DB_HW_VRM:
-   name = "VRM";
-   break;
-   case CMD_DB_HW_BCM:
-   name = "BCM";
-   break;
-   default:
-   name = "Unknown";
-   break;
-   }
-
-   version = le16_to_cpu(rsc->version);
-   major = version >> 8;
-   minor = version;
-
-   seq_printf(seq, "Slave %s (v%u.%u)\n", name, major, minor);
-   seq_puts(seq, "-\n");
-
-   ent = rsc_to_entry_header(rsc);
-   for (j = 0; j < le16_to_cpu(rsc->cnt); j++, ent++) {
-   seq_printf(seq, "0x%05x: %*pEp", le32_to_cpu(ent->addr),
-  (int)strnlen(ent->id, sizeof(ent->id)), 
ent->id);
-
-   len = le16_to_cpu(ent->len);
-   if (len) {
-   seq_printf(seq, " [%*ph]",
-  len, rsc_offset(rsc, ent));
-   }
-   seq_putc(seq, '\n');
-   }
-   }
-
-   return 0;
-}
-
-static int open_cmd_db_debugfs(struct inode *inode, struct file *file)
-{
-   return single_open(file, cmd_db_debugfs_dump, inode->i_private);
-}
-#endif
-
-static const struct file_operations cmd_db_debugfs_ops = {
-#ifdef CONFIG_DEBUG_FS
-   .open = open_cmd_db_debugfs,
-#endif
-   .read = seq_rea

[PATCH v6 03/24] soc: qcom: import rpmh and cmd-db drivers from Linux

2024-07-15 Thread Caleb Connolly
Import RPMh and cmd-db framework from Linux 6.10-rc6.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c|  393 +
 drivers/soc/qcom/rpmh-internal.h |  148 +
 drivers/soc/qcom/rpmh-rsc.c  | 1162 ++
 drivers/soc/qcom/rpmh.c  |  502 
 include/soc/qcom/cmd-db.h|   48 ++
 include/soc/qcom/rpmh.h  |   47 ++
 include/soc/qcom/tcs.h   |   81 +++
 7 files changed, 2381 insertions(+)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
new file mode 100644
index ..d84572662017
--- /dev/null
+++ b/drivers/soc/qcom/cmd-db.c
@@ -0,0 +1,393 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define NUM_PRIORITY   2
+#define MAX_SLV_ID 8
+#define SLAVE_ID_MASK  0x7
+#define SLAVE_ID_SHIFT 16
+#define SLAVE_ID(addr) FIELD_GET(GENMASK(19, 16), addr)
+#define VRM_ADDR(addr) FIELD_GET(GENMASK(19, 4), addr)
+
+/**
+ * struct entry_header: header for each entry in cmddb
+ *
+ * @id: resource's identifier
+ * @priority: unused
+ * @addr: the address of the resource
+ * @len: length of the data
+ * @offset: offset from :@data_offset, start of the data
+ */
+struct entry_header {
+   u8 id[8];
+   __le32 priority[NUM_PRIORITY];
+   __le32 addr;
+   __le16 len;
+   __le16 offset;
+};
+
+/**
+ * struct rsc_hdr: resource header information
+ *
+ * @slv_id: id for the resource
+ * @header_offset: entry's header at offset from the end of the cmd_db_header
+ * @data_offset: entry's data at offset from the end of the cmd_db_header
+ * @cnt: number of entries for HW type
+ * @version: MSB is major, LSB is minor
+ * @reserved: reserved for future use.
+ */
+struct rsc_hdr {
+   __le16 slv_id;
+   __le16 header_offset;
+   __le16 data_offset;
+   __le16 cnt;
+   __le16 version;
+   __le16 reserved[3];
+};
+
+/**
+ * struct cmd_db_header: The DB header information
+ *
+ * @version: The cmd db version
+ * @magic: constant expected in the database
+ * @header: array of resources
+ * @checksum: checksum for the header. Unused.
+ * @reserved: reserved memory
+ * @data: driver specific data
+ */
+struct cmd_db_header {
+   __le32 version;
+   u8 magic[4];
+   struct rsc_hdr header[MAX_SLV_ID];
+   __le32 checksum;
+   __le32 reserved;
+   u8 data[];
+};
+
+/**
+ * DOC: Description of the Command DB database.
+ *
+ * At the start of the command DB memory is the cmd_db_header structure.
+ * The cmd_db_header holds the version, checksum, magic key as well as an
+ * array for header for each slave (depicted by the rsc_header). Each h/w
+ * based accelerator is a 'slave' (shared resource) and has slave id indicating
+ * the type of accelerator. The rsc_header is the header for such individual
+ * slaves of a given type. The entries for each of these slaves begin at the
+ * rsc_hdr.header_offset. In addition each slave could have auxiliary data
+ * that may be needed by the driver. The data for the slave starts at the
+ * entry_header.offset to the location pointed to by the rsc_hdr.data_offset.
+ *
+ * Drivers have a stringified key to a slave/resource. They can query the slave
+ * information and get the slave id and the auxiliary data and the length of 
the
+ * data. Using this information, they can format the request to be sent to the
+ * h/w accelerator and request a resource state.
+ */
+
+static const u8 CMD_DB_MAGIC[] = { 0xdb, 0x30, 0x03, 0x0c };
+
+static bool cmd_db_magic_matches(const struct cmd_db_header *header)
+{
+   const u8 *magic = header->magic;
+
+   return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
+}
+
+static struct cmd_db_header *cmd_db_header;
+
+static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
+{
+   u16 offset = le16_to_cpu(hdr->header_offset);
+
+   return cmd_db_header->data + offset;
+}
+
+static inline void *
+rsc_offset(const struct rsc_hdr *hdr, const struct entry_header *ent)
+{
+   u16 offset = le16_to_cpu(hdr->data_offset);
+   u16 loffset = le16_to_cpu(ent->offset);
+
+   return cmd_db_header->data + offset + loffset;
+}
+
+/**
+ * cmd_db_ready - Indicates if command DB is available
+ *
+ * Return: 0 on success, errno otherwise
+ */
+int cmd_db_ready(void)
+{
+   if (cmd_db_header == NULL)
+   return -EPROBE_DEFER;
+   else if (!cmd_db_magic_matches(cmd_db_header))
+   return -EINVAL;
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(cmd_db_ready);
+
+static int cmd_db_get_header(const char *id, const struct

[PATCH v6 04/24] soc: qcom: cmd-db: adjust headers for U-Boot

2024-07-15 Thread Caleb Connolly
Replace unused/unsupported Linux headers with appropriate U-Boot
alternatives.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index d84572662017..b25f3549c18f 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -3,18 +3,17 @@
  * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
  * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
-#include 
-#include 
+#define pr_fmt(fmt) "cmd-db: " fmt
+
+#include 
+#include 
+#include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
 #include 
+#include 
+#include 
 
 #include 
 
 #define NUM_PRIORITY   2

-- 
2.45.2



[PATCH v6 02/24] linux/bitmap.h: add bitmap_empty helper

2024-07-15 Thread Caleb Connolly
Import this function from Linux as of 6.10-rc6

Reviewed-by: Tom Rini 
Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 include/linux/bitmap.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f14..40ca2212cb40 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -195,8 +195,16 @@ static inline void bitmap_fill(unsigned long *dst, 
unsigned int nbits)
memset(dst, 0xff, len);
}
 }
 
+static inline bool bitmap_empty(const unsigned long *src, unsigned int nbits)
+{
+   if (small_const_nbits(nbits))
+   return !(*src & BITMAP_LAST_WORD_MASK(nbits));
+
+   return find_first_bit(src, nbits) == nbits;
+}
+
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
 const unsigned long *src2, unsigned int nbits)
 {
if (small_const_nbits(nbits))

-- 
2.45.2



[PATCH v6 01/24] dm: core: scan reserved-memory nodes

2024-07-15 Thread Caleb Connolly
Qualcomm platforms may have drivers that bind to reserved memory nodes
(cmd-db [1] and smem [2]) which are relevant to U-Boot. Include
/reserved-memory in dm_extended_scan() so that these will be handled
correctly.

[1]: 
https://www.kernel.org/doc/Documentation/devicetree/bindings/reserved-memory/qcom%2Ccmd-db.yaml
[2]: 
https://www.kernel.org/doc/Documentation/devicetree/bindings/soc/qcom/qcom%2Csmem.yaml

Signed-off-by: Caleb Connolly 
---
To: Simon Glass 
---
 drivers/core/root.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/core/root.c b/drivers/core/root.c
index 7cf6607a9b7b..7a714f5478a9 100644
--- a/drivers/core/root.c
+++ b/drivers/core/root.c
@@ -242,9 +242,10 @@ int dm_extended_scan(bool pre_reloc_only)
int ret, i;
const char * const nodes[] = {
"/chosen",
"/clocks",
-   "/firmware"
+   "/firmware",
+   "/reserved-memory",
};
 
ret = dm_scan_fdt(pre_reloc_only);
if (ret) {

-- 
2.45.2



[PATCH v6 00/24] qcom: rpmh core and regulator support

2024-07-15 Thread Caleb Connolly
This series introduces support for the RPMh (Resource Power Manager
(hardened)) co-processor and associated regulator driver found on most
modern Qualcomm platforms (since ~2017).

Even though most regulators are controlled via SPMI, the specific
regions on the PMICs for controlling the regulators are restricted and
can't be accessed by the Applications Processor (AP/HLOS). Instead,
these resources are proxied via the RPMh where they can be voted on by
multiple subsystems (Linux, the modem, and the other DSPs). This is done
for security (to protect clocks, power domains, and regulators that are
specifically relevant for the trustzone) as well as to simplify the
management of shared peripherals and to allow for handover of
peripherals like the USB controller.

For U-Boot, our main concern is the regulators. Since all regulators on
the system are controlled via the RPMh, it is necessary to support it to
enable USB VBUS on some platforms, and may be needed for other
peripherals in the future.

Communicating with the RPMh additional requires accessing the cmd-db
shared memory region, this contains key/value maps to determine the
address of specific resources on the RPMh.

Introduce support for the cmd-db, the RPMh framework, and some of the
regulators that are necessary to enable USB VBUS on the RB5 development
board.

These drivers are taken from Linux, then modified and simplified for
U-Boot. The original Linux drivers contain heavy optimisations related
to multithreading and asynchronous probing, as well as support for idle
and suspend states which we don't need to deal with here. This unused
code is removed before finally adjusting the drivers to properly build
for U-Boot and use its device model.

The U-Boot version of the driver supports a single ACTIVE_ONLY TCS and
waits for it to be cleared after use. We don't support programming
low power states.

To: Tom Rini 
To: Caleb Connolly 
To: Neil Armstrong 
To: Sumit Garg 
To: Jaehoon Chung 
To: Simon Glass 
Cc: u-boot@lists.denx.de
Cc: u-boot-q...@groups.io

Changes in v6:
- Use the driver model for cmd-db
- Extend dm_extended_scan() to scan nodes under /reserved-memory so that
  cmd-db will be bound.
- Link to v5: 
https://lore.kernel.org/r/20240711-b4-qcom-rpmh-v5-0-fbf04ce6a...@linaro.org

Changes in v5:
- Add Kconfig / Makefiles after introducing drivers to avoid breaking
  compilation when bisecting (Thanks Neil).
- Link to v4: 
https://lore.kernel.org/r/20240709-b4-qcom-rpmh-v4-0-c06d0a266...@linaro.org

Changes in v4:
- Denote original Linux version in bitmap.h patch
- Rebased on Linux 6.10-rc6 and re-apply U-Boot changes preserving git
  history. Allowing for future changes to the Linux drivers to be ported
  over more easily.
- Add missing check to wait for the TCS to be cleared after use (seems
  we were just racing the RPMh before, oops!).
- Fix missing n_modes in pmic5_pldo regulator.
- Link to v3: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v3-0-846cc6c5b...@linaro.org

Changes in v3:
- Don't call dm_scan_fdt_dev(), since DM core will scan.
- Link to v2: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v2-0-8bc765606...@linaro.org

Changes in v2:
- Implement Neil's suggestions and fixes for SM8[56]50
- Slightly refactor cmd_db_init() for better abstraction.
- Improve logging (printf -> log_err/dev_err)
- Add missing error check in rpmh_regulators_bind()
- Link to v1: 
https://lore.kernel.org/r/20240617-b4-qcom-rpmh-v1-0-bd2336923...@linaro.org

---
Caleb Connolly (24):
  dm: core: scan reserved-memory nodes
  linux/bitmap.h: add bitmap_empty helper
  soc: qcom: import rpmh and cmd-db drivers from Linux
  soc: qcom: cmd-db: adjust headers for U-Boot
  soc: qcom: cmd-db: drop unused functions
  soc: qcom: cmd-db: adjust probe for U-Boot
  soc: qcom: cmd-db: adjust for U-Boot API
  soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS 
support
  soc: qcom: rpmh-rsc: adjust headers for U-Boot
  soc: qcom: rpmh-rsc: adjust probe for U-Boot
  soc: qcom: rpmh-rsc: remaining U-Boot API changes
  soc: qcom: rpmh: adjust headers for U-Boot
  soc: qcom: rpmh: drop unused functions
  soc: qcom: rpmh: U-Boot API changes
  soc: qcom: add build infrastructure
  power: regulator: import qcom-rpmh-regulator from Linux
  power: regulator: qcom-rpmh-regulator: adjust headers for U-Boot
  power: regulator: qcom-rpmh-regulator: port over lineage_range helpers
  power: regulator: qcom-rpmh-regulator: adjust structs for U-Boot
  power: regulator: qcom-rpmh-regulator: remove unused regulators
  power: regulator: qcom-rpmh-regulator: port ops to U-Boot
  power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot
  power: regulator: qcom-rpmh-regulator: add build infra
  qcom_defconfig: enable rpmh regulators

 configs/qcom_defconfig|   5 +
 drivers/core/root.c   |   3 +-
 drivers/power/regulator/Kcon

Re: [PATCH] dm: button: support remapping phone keys

2024-07-15 Thread Caleb Connolly

Hi Quentin,

+static int button_remap_phone_keys(int code)
+{
+    switch (code) {
+    case KEY_VOLUMEUP:
+    return KEY_UP;
+    case KEY_VOLUMEDOWN:
+    return KEY_DOWN;
+    case KEY_POWER:
+    return KEY_ENTER;
+    default:
+    return code;
+    }
+}
+


... I suggest to make this a weak function that can be overridden by 
boards (should it maybe be only defined in boards C file?) so that it's 
easy for people to come up with their own mapping without having to deal 
with two people/the maintainer disagreeing with what should be the one 
and true mapping for that key.


This is intentionally not a board specific feature. It is a generic 
option that does precisely one thing: remap the keys on a phone to be 
useful for navigating boot menus.


If some folks have a strong disagreement about e.g. what KEY_CAMERA 
should be (for the devices that have it) then I would rather propose 
making this all configurable via an environment variable, or better yet 
introducing a new bootloader,code property in devicetree to define what 
a key should do in a bootloader.


Cheers,
Quentin


--
// Caleb (they/them)


Re: [PATCH] dm: button: support remapping phone keys

2024-07-15 Thread Caleb Connolly

Hi Quentin,

On 15/07/2024 10:16, Quentin Schulz wrote:

Hi Caleb,

On 7/14/24 9:49 PM, Caleb Connolly wrote:

We don't have audio support in U-Boot, but we do have boot menus. Add an
option to re-map the volume and power buttons to up/down/enter so that
in situations where these are the only available buttons (such as on
mobile phones) it's still possible to navigate menus built in U-Boot or
an external EFI app like GRUB or systemd-boot.



Are those event codes properly defined in the DT already?

e.g. 
https://elixir.bootlin.com/linux/latest/source/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts#L31


If so, what prevents us from simply patching the U-Boot DT to change 
that code? No additional code required anywhere, no need to maintain a 
list of mapping, etc...


Many platforms in U-Boot are now switching to upstream DT, and 
SystemReady compliance requires that the bootloader provide a DT to the 
kernel.


U-Boot doesn't really have a generic way to apply specific adjustments 
to FDT for U-Boot without them being carried over to the kernel.


Patching FDT is in and of itself somewhat treacherous without using 
OF_LIVE, which isn't set up until after bind(), making it unsuitable. 
It's also vastly slower to patch FDT than to patch a livetree.


I couldn't conceive of a way to do via patching DT that wouldn't require 
solving the above problems, I also couldn't think of another example 
that would justify making this patch more generic or configurable.


Kind regards,


If that isn't possible, .


Signed-off-by: Caleb Connolly 
---
Cc: u-boot-q...@groups.io
---
  drivers/button/Kconfig | 11 +++
  drivers/button/button-uclass.c | 22 +-
  2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig
index 3918b05ae03e..6cae16fcc8bf 100644
--- a/drivers/button/Kconfig
+++ b/drivers/button/Kconfig
@@ -8,8 +8,19 @@ config BUTTON
    U-Boot provides a uclass API to implement this feature. Button 
drivers
    can provide access to board-specific buttons. Use of the 
device tree

    for configuration is encouraged.
+config BUTTON_REMAP_PHONE_KEYS
+    bool "Remap phone keys for navigation"
+    depends on BUTTON
+    help
+  Enable remapping of phone keys to navigation keys. This is 
useful for
+  devices with phone keys that are not used in U-Boot. The phone 
keys

+  are remapped to the following navigation keys:
+  - Volume up: Up
+  - Volume down: Down
+  - Power: Enter
+
  config BUTTON_ADC
  bool "Button adc"
  depends on BUTTON
  depends on ADC
diff --git a/drivers/button/button-uclass.c 
b/drivers/button/button-uclass.c

index cda243389df3..729983d58701 100644
--- a/drivers/button/button-uclass.c
+++ b/drivers/button/button-uclass.c
@@ -9,8 +9,9 @@
  #include 
  #include 
  #include 
+#include 
  int button_get_by_label(const char *label, struct udevice **devp)
  {
  struct udevice *dev;
@@ -36,16 +37,35 @@ enum button_state_t button_get_state(struct 
udevice *dev)

  return ops->get_state(dev);
  }
+static int button_remap_phone_keys(int code)
+{
+    switch (code) {
+    case KEY_VOLUMEUP:
+    return KEY_UP;
+    case KEY_VOLUMEDOWN:
+    return KEY_DOWN;
+    case KEY_POWER:
+    return KEY_ENTER;
+    default:
+    return code;
+    }
+}
+


... I suggest to make this a weak function that can be overridden by 
boards (should it maybe be only defined in boards C file?) so that it's 
easy for people to come up with their own mapping without having to deal 
with two people/the maintainer disagreeing with what should be the one 
and true mapping for that key.


Cheers,
Quentin


--
// Caleb (they/them)


Re: [PATCH] dm: button: support remapping phone keys

2024-07-15 Thread Caleb Connolly




On 15/07/2024 09:03, Dragan Simic wrote:

Hello Caleb,

On 2024-07-15 08:24, Caleb Connolly wrote:

On 14/07/2024 22:47, Dragan Simic wrote:

On 2024-07-14 21:49, Caleb Connolly wrote:
We don't have audio support in U-Boot, but we do have boot menus. 
Add an

option to re-map the volume and power buttons to up/down/enter so that
in situations where these are the only available buttons (such as on
mobile phones) it's still possible to navigate menus built in U-Boot or
an external EFI app like GRUB or systemd-boot.

Signed-off-by: Caleb Connolly 
---
Cc: u-boot-q...@groups.io


Very nice, thanks for this patch!  Looking good to me, with a few
suggestions available below.  Anyway, please feel free to add:

Reviewed-by: Dragan Simic 


---
 drivers/button/Kconfig | 11 +++
 drivers/button/button-uclass.c | 22 +-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig
index 3918b05ae03e..6cae16fcc8bf 100644
--- a/drivers/button/Kconfig
+++ b/drivers/button/Kconfig
@@ -8,8 +8,19 @@ config BUTTON
   U-Boot provides a uclass API to implement this feature. 
Button drivers
   can provide access to board-specific buttons. Use of the 
device tree

   for configuration is encouraged.

+config BUTTON_REMAP_PHONE_KEYS
+    bool "Remap phone keys for navigation"
+    depends on BUTTON
+    help
+  Enable remapping of phone keys to navigation keys. This is 
useful for
+  devices with phone keys that are not used in U-Boot. The 
phone keys

+  are remapped to the following navigation keys:
+  - Volume up: Up
+  - Volume down: Down
+  - Power: Enter
+


Frankly, "phone keys" sounds a bit strange to me, maybe because there
are also tablets that have the same style of reduced-set keys.  Thus,
I'd suggest that the following language is used:

- "BUTTON_REMAP_PHONE_KEYS" instead of "BUTTON_REMAP_REDUCED_KEYS"
- "reduced smartphone-style keys" instead of "phone keys"


I would have assumed that anyone working on a tablet would immediately
guess what this option does and that it might be useful given the
name. I would argue that seeing "BUTTON_REMAP_REDUCED_KEYS" instead
makes it harder to guess what this option does.

I think of it not as "this option remaps the keys on your phone" but
as "this option remaps the keys that phones have", as in, the volume
and power buttons.

If you'd prefer, maybe we can meet somewhere in the middle with "mobile"?

how's BUTTON_REMAP_MOBILE_KEYS?


Hmm, if I had to choose between BUTTON_REMAP_PHONE_KEYS and
BUTTON_REMAP_MOBILE_KEYS, I'd still choose BUTTON_REMAP_PHONE_KEYS.
As you're against BUTTON_REMAP_REDUCED_KEYS, for which you provided
valid arguments, I'm still fine with your original word choice.

In other words, there are no reasons for the word choice to hold
this nice patch back from becoming accepted.


Ok, thanks :)

Sorry for the tone, I'm afraid I misread your original email.

Kind regards,



Using "reduced" would also allow us to have this remapping logic more
easily extended to also cover some other buttons found on some other
devices with reduced-set keys.


If such a device exists and gains support in U-Boot, the switch/case
could be extended, or a new option added if it doesn't make sense to
lump everything together. Without knowing about such a device I think
it's impossible to make a judgement here.


I see, but I just tried to make it a bit more future-proof by using
more general terms.  However, as I already wrote above, I'm fine with
keeping the patch in its original form.


 config BUTTON_ADC
 bool "Button adc"
 depends on BUTTON
 depends on ADC
diff --git a/drivers/button/button-uclass.c 
b/drivers/button/button-uclass.c

index cda243389df3..729983d58701 100644
--- a/drivers/button/button-uclass.c
+++ b/drivers/button/button-uclass.c
@@ -9,8 +9,9 @@

 #include 
 #include 
 #include 
+#include 

 int button_get_by_label(const char *label, struct udevice **devp)
 {
 struct udevice *dev;
@@ -36,16 +37,35 @@ enum button_state_t button_get_state(struct 
udevice *dev)


 return ops->get_state(dev);
 }

+static int button_remap_phone_keys(int code)


Pretty much the same suggestion as above applies here.


+{
+    switch (code) {
+    case KEY_VOLUMEUP:
+    return KEY_UP;
+    case KEY_VOLUMEDOWN:
+    return KEY_DOWN;
+    case KEY_POWER:
+    return KEY_ENTER;
+    default:
+    return code;
+    }
+}
+
 int button_get_code(struct udevice *dev)
 {
 struct button_ops *ops = button_get_ops(dev);
+    int code;

 if (!ops->get_code)
 return -ENOSYS;

-    return ops->get_code(dev);
+    code = ops->get_code(dev);
+    if (CONFIG_IS_ENABLED(BUTTON_REMAP_PHONE_KEYS))
+    return button_remap_phone_keys(code);
+    else
+    return code;
 }

 UCLASS_DRIVER(button) = {
 .id    = UCLASS_BUTTON,


--
// Caleb (they/them)


Re: [PATCH] dm: button: support remapping phone keys

2024-07-15 Thread Caleb Connolly

Hi Dragan,

On 14/07/2024 22:47, Dragan Simic wrote:

Hello Caleb,

On 2024-07-14 21:49, Caleb Connolly wrote:

We don't have audio support in U-Boot, but we do have boot menus. Add an
option to re-map the volume and power buttons to up/down/enter so that
in situations where these are the only available buttons (such as on
mobile phones) it's still possible to navigate menus built in U-Boot or
an external EFI app like GRUB or systemd-boot.

Signed-off-by: Caleb Connolly 
---
Cc: u-boot-q...@groups.io


Very nice, thanks for this patch!  Looking good to me, with a few
suggestions available below.  Anyway, please feel free to add:

Reviewed-by: Dragan Simic 


---
 drivers/button/Kconfig | 11 +++
 drivers/button/button-uclass.c | 22 +-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig
index 3918b05ae03e..6cae16fcc8bf 100644
--- a/drivers/button/Kconfig
+++ b/drivers/button/Kconfig
@@ -8,8 +8,19 @@ config BUTTON
   U-Boot provides a uclass API to implement this feature. Button 
drivers
   can provide access to board-specific buttons. Use of the device 
tree

   for configuration is encouraged.

+config BUTTON_REMAP_PHONE_KEYS
+    bool "Remap phone keys for navigation"
+    depends on BUTTON
+    help
+  Enable remapping of phone keys to navigation keys. This is 
useful for
+  devices with phone keys that are not used in U-Boot. The phone 
keys

+  are remapped to the following navigation keys:
+  - Volume up: Up
+  - Volume down: Down
+  - Power: Enter
+


Frankly, "phone keys" sounds a bit strange to me, maybe because there
are also tablets that have the same style of reduced-set keys.  Thus,
I'd suggest that the following language is used:

- "BUTTON_REMAP_PHONE_KEYS" instead of "BUTTON_REMAP_REDUCED_KEYS"
- "reduced smartphone-style keys" instead of "phone keys"


I would have assumed that anyone working on a tablet would immediately 
guess what this option does and that it might be useful given the name. 
I would argue that seeing "BUTTON_REMAP_REDUCED_KEYS" instead makes it 
harder to guess what this option does.


I think of it not as "this option remaps the keys on your phone" but as 
"this option remaps the keys that phones have", as in, the volume and 
power buttons.


If you'd prefer, maybe we can meet somewhere in the middle with "mobile"?

how's BUTTON_REMAP_MOBILE_KEYS?


Using "reduced" would also allow us to have this remapping logic more
easily extended to also cover some other buttons found on some other
devices with reduced-set keys.


If such a device exists and gains support in U-Boot, the switch/case 
could be extended, or a new option added if it doesn't make sense to 
lump everything together. Without knowing about such a device I think 
it's impossible to make a judgement here.





 config BUTTON_ADC
 bool "Button adc"
 depends on BUTTON
 depends on ADC
diff --git a/drivers/button/button-uclass.c 
b/drivers/button/button-uclass.c

index cda243389df3..729983d58701 100644
--- a/drivers/button/button-uclass.c
+++ b/drivers/button/button-uclass.c
@@ -9,8 +9,9 @@

 #include 
 #include 
 #include 
+#include 

 int button_get_by_label(const char *label, struct udevice **devp)
 {
 struct udevice *dev;
@@ -36,16 +37,35 @@ enum button_state_t button_get_state(struct 
udevice *dev)


 return ops->get_state(dev);
 }

+static int button_remap_phone_keys(int code)


Pretty much the same suggestion as above applies here.


+{
+    switch (code) {
+    case KEY_VOLUMEUP:
+    return KEY_UP;
+    case KEY_VOLUMEDOWN:
+    return KEY_DOWN;
+    case KEY_POWER:
+    return KEY_ENTER;
+    default:
+    return code;
+    }
+}
+
 int button_get_code(struct udevice *dev)
 {
 struct button_ops *ops = button_get_ops(dev);
+    int code;

 if (!ops->get_code)
 return -ENOSYS;

-    return ops->get_code(dev);
+    code = ops->get_code(dev);
+    if (CONFIG_IS_ENABLED(BUTTON_REMAP_PHONE_KEYS))
+    return button_remap_phone_keys(code);
+    else
+    return code;
 }

 UCLASS_DRIVER(button) = {
 .id    = UCLASS_BUTTON,


--
// Caleb (they/them)


[PATCH] dm: button: support remapping phone keys

2024-07-14 Thread Caleb Connolly
We don't have audio support in U-Boot, but we do have boot menus. Add an
option to re-map the volume and power buttons to up/down/enter so that
in situations where these are the only available buttons (such as on
mobile phones) it's still possible to navigate menus built in U-Boot or
an external EFI app like GRUB or systemd-boot.

Signed-off-by: Caleb Connolly 
---
Cc: u-boot-q...@groups.io
---
 drivers/button/Kconfig | 11 +++
 drivers/button/button-uclass.c | 22 +-
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/drivers/button/Kconfig b/drivers/button/Kconfig
index 3918b05ae03e..6cae16fcc8bf 100644
--- a/drivers/button/Kconfig
+++ b/drivers/button/Kconfig
@@ -8,8 +8,19 @@ config BUTTON
  U-Boot provides a uclass API to implement this feature. Button drivers
  can provide access to board-specific buttons. Use of the device tree
  for configuration is encouraged.
 
+config BUTTON_REMAP_PHONE_KEYS
+   bool "Remap phone keys for navigation"
+   depends on BUTTON
+   help
+ Enable remapping of phone keys to navigation keys. This is useful for
+ devices with phone keys that are not used in U-Boot. The phone keys
+ are remapped to the following navigation keys:
+ - Volume up: Up
+ - Volume down: Down
+ - Power: Enter
+
 config BUTTON_ADC
bool "Button adc"
depends on BUTTON
depends on ADC
diff --git a/drivers/button/button-uclass.c b/drivers/button/button-uclass.c
index cda243389df3..729983d58701 100644
--- a/drivers/button/button-uclass.c
+++ b/drivers/button/button-uclass.c
@@ -9,8 +9,9 @@
 
 #include 
 #include 
 #include 
+#include 
 
 int button_get_by_label(const char *label, struct udevice **devp)
 {
struct udevice *dev;
@@ -36,16 +37,35 @@ enum button_state_t button_get_state(struct udevice *dev)
 
return ops->get_state(dev);
 }
 
+static int button_remap_phone_keys(int code)
+{
+   switch (code) {
+   case KEY_VOLUMEUP:
+   return KEY_UP;
+   case KEY_VOLUMEDOWN:
+   return KEY_DOWN;
+   case KEY_POWER:
+   return KEY_ENTER;
+   default:
+   return code;
+   }
+}
+
 int button_get_code(struct udevice *dev)
 {
struct button_ops *ops = button_get_ops(dev);
+   int code;
 
if (!ops->get_code)
return -ENOSYS;
 
-   return ops->get_code(dev);
+   code = ops->get_code(dev);
+   if (CONFIG_IS_ENABLED(BUTTON_REMAP_PHONE_KEYS))
+   return button_remap_phone_keys(code);
+   else
+   return code;
 }
 
 UCLASS_DRIVER(button) = {
.id = UCLASS_BUTTON,
-- 
2.45.2



Re: [PATCH RFC 0/3] ARM64: add symbol name lookup and print a backtrace on exception

2024-07-14 Thread Caleb Connolly




On 12/07/2024 18:48, Tom Rini wrote:

On Wed, Jul 10, 2024 at 06:26:17PM +0200, Caleb Connolly wrote:


U-Boot already emits frame pointers on ARM64, but lacks the code to
parse them, as well as a mechanism for looking up symbol names at
runtime.

There was some (seemingly?) leftover code for symbols lookups in
common/kallsyms.c and associated parts in the makefile, however it
appears to be entirely unused and unsupported. It relied on generating
one long string of all symbol addresses and names.

The approach taken here is instead largely based on the implementation
in the Xen hypervisor, it performs basic compression using non-ASCII
bytes to tokenize repeated string segments which can later be expanded
back out at runtime.

This is then utilized in the ARM64 interrupt handling routine to dump a
backtrace in the show_regs() debug function. As well as providing a
general purpose unwind_stack() function which can be used for debugging.


Just a few minor comments from me in general, and I'm glad to see this.
Please submit the next version non-RFC, thanks.


Thanks for the review.

One thing I'm a little unsure about before sending the next version: is 
it better to print the address in the link register or the address of 
the function in the backtrace?


In the example below I print the function address offset by _start, but 
that doesn't seem very useful for either interactive debugging or 
decompilation. Maybe the absolute address in the link register would be 
more useful.


I'm leaning towards the latter, but open to ideas.

Backtrace:
<0x01bb4c> do_mem_mw+0xbc
<0x00bb729cec> cmd_process+0x130
<0x00bb7213f8> run_list_real+0x6d0
<0x00bb721b08> parse_stream_outer+0x14c
<0x00bb722164> parse_file_outer+0x34
<0x00bb72929c> cli_loop+0x1c
<0x00bb71f1dc> main_loop+0x54
<0x00bb7229dc> run_main_loop+0x14
<0x00bb777664> initcall_run_list+0x7c
<0x00bb722bf8> board_init_r+0x34




--
// Caleb (they/them)


[PATCH v5 23/23] qcom_defconfig: enable rpmh regulators

2024-07-11 Thread Caleb Connolly
Enable RPMh, cmd-db, and RPMh regulators. Additionally enable
CMD_REGULATOR for debugging.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 configs/qcom_defconfig | 5 +
 1 file changed, 5 insertions(+)

diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index ac5ffe772ade..1cbad9db72eb 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -35,8 +35,9 @@ CONFIG_CMD_UFS=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_CAT=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_LOG=y
 CONFIG_OF_LIVE=y
 CONFIG_BUTTON_QCOM_PMIC=y
 CONFIG_CLK=y
@@ -90,11 +91,15 @@ CONFIG_PINCTRL_QCOM_SM8650=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_QCOM=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_QCOM_RPMH=y
 CONFIG_SCSI=y
 CONFIG_MSM_SERIAL=y
 CONFIG_MSM_GENI_SERIAL=y
+CONFIG_SOC_QCOM=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_QCOM_RPMH=y
 CONFIG_SPMI_MSM=y
 CONFIG_SYSINFO=y
 CONFIG_SYSINFO_SMBIOS=y
 CONFIG_USB=y

-- 
2.45.2



[PATCH v5 22/23] power: regulator: qcom-rpmh-regulator: add build infra

2024-07-11 Thread Caleb Connolly
Add Kconfig and Makefile entries for this driver now that it can build
for U-Boot.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/Kconfig  | 8 
 drivers/power/regulator/Makefile | 1 +
 2 files changed, 9 insertions(+)

diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 102ec7bc5f89..bc061c20d75e 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -215,8 +215,16 @@ config DM_REGULATOR_GPIO
This config enables implementation of driver-model regulator uclass
features for gpio regulators. The driver implements get/set for
voltage value.
 
+config DM_REGULATOR_QCOM_RPMH
+   bool "Enable driver model for Qualcomm RPMh regulator"
+   depends on DM_REGULATOR && QCOM_RPMH
+   ---help---
+ Enable support for the Qualcomm RPMh regulator. The driver
+ implements get/set api for a limited set of regulators used
+ by u-boot.
+
 config SPL_DM_REGULATOR_GPIO
bool "Enable Driver Model for GPIO REGULATOR in SPL"
depends on DM_REGULATOR_GPIO && SPL_GPIO
select SPL_DM_REGULATOR_COMMON
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index f79932d83307..56a527612b74 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -20,8 +20,9 @@ obj-$(CONFIG_$(SPL_)REGULATOR_PWM) += pwm_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_COMMON) += regulator_common.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
+obj-$(CONFIG_DM_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
 obj-$(CONFIG_$(SPL_TPL_)REGULATOR_RK8XX) += rk8xx.o
 obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o

-- 
2.45.2



[PATCH v5 21/23] power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot

2024-07-11 Thread Caleb Connolly
Refactor initialization to use U-Boot's driver model and API.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 136 +++---
 1 file changed, 102 insertions(+), 34 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index b716b380c148..06fd3f31956f 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -411,66 +411,134 @@ static const struct rpmh_vreg_init_data 
pm8150l_vreg_data[] = {
RPMH_VREG("ldo11",  "ldo%s11", _pldo,  "vdd-l7-l11"),
{}
 };
 
-static int rpmh_regulator_probe(struct platform_device *pdev)
+/* probe an individual regulator */
+static int rpmh_regulator_probe(struct udevice *dev)
 {
-   struct device *dev = >dev;
-   const struct rpmh_vreg_init_data *vreg_data;
-   struct device_node *node;
-   struct rpmh_vreg *vreg;
-   const char *pmic_id;
-   int ret;
+   const struct rpmh_vreg_init_data *init_data;
+   struct rpmh_vreg *priv;
+   struct dm_regulator_uclass_plat *plat_data;
 
-   vreg_data = of_device_get_match_data(dev);
-   if (!vreg_data)
+   init_data = (const struct rpmh_vreg_init_data 
*)dev_get_driver_data(dev);
+   priv = dev_get_priv(dev);
+   plat_data = dev_get_uclass_plat(dev);
+
+   priv->dev = dev;
+   priv->addr = cmd_db_read_addr(dev->name);
+   if (!priv->addr) {
+   dev_err(dev, "Failed to read RPMh address for %s\n", dev->name);
return -ENODEV;
-
-   ret = of_property_read_string(dev->of_node, "qcom,pmic-id", _id);
-   if (ret < 0) {
-   dev_err(dev, "qcom,pmic-id missing in DT node\n");
-   return ret;
}
 
-   for_each_available_child_of_node(dev->of_node, node) {
-   vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
-   if (!vreg) {
-   of_node_put(node);
+   priv->hw_data = init_data->hw_data;
+   priv->enabled = -EINVAL;
+   priv->uv = -ENOTRECOVERABLE;
+   if (ofnode_read_u32(dev_ofnode(dev), "regulator-initial-mode", 
>mode))
+   priv->mode = -EINVAL;
+
+   plat_data->mode = priv->hw_data->pmic_mode_map;
+   plat_data->mode_count = priv->hw_data->n_modes;
+
+   return 0;
+}
+
+/* for non-drm, xob, or bypass regulators add additional driver definitions */
+U_BOOT_DRIVER(rpmh_regulator_drm) = {
+   .name = "rpmh_regulator_drm",
+   .id = UCLASS_REGULATOR,
+   .probe = rpmh_regulator_probe,
+   .priv_auto = sizeof(struct rpmh_vreg),
+   .ops = _regulator_vrm_drms_ops,
+};
+
+/* This driver intentionally only supports a subset of the available 
regulators.
+ * This function checks to see if a given regulator node in DT matches a 
regulator
+ * defined in the driver.
+ */
+static const struct rpmh_vreg_init_data *
+vreg_get_init_data(const struct rpmh_vreg_init_data *init_data, ofnode node)
+{
+   const struct rpmh_vreg_init_data *data;
+
+   for (data = init_data; data->name; data++) {
+   if (!strcmp(data->name, ofnode_get_name(node)))
+   return data;
+   }
+
+   return NULL;
+}
+
+static int rpmh_regulators_bind(struct udevice *dev)
+{
+   const struct rpmh_vreg_init_data *init_data, *data;
+   const char *pmic_id;
+   char *name;
+   struct driver *drv;
+   ofnode node;
+   int ret;
+   size_t namelen;
+
+   init_data = (const struct rpmh_vreg_init_data 
*)dev_get_driver_data(dev);
+   if (!init_data) {
+   dev_err(dev, "No RPMh regulator init data\n");
+   return -ENODEV;
+   }
+
+   pmic_id = ofnode_read_string(dev_ofnode(dev), "qcom,pmic-id");
+   if (!pmic_id) {
+   dev_err(dev, "No PMIC ID\n");
+   return -ENODEV;
+   }
+
+   drv = lists_driver_lookup_name("rpmh_regulator_drm");
+
+   ofnode_for_each_subnode(node, dev_ofnode(dev)) {
+   data = vreg_get_init_data(init_data, node);
+   if (!data)
+   continue;
+
+   /* %s is replaced with pmic_id, so subtract 2, then add 1 for 
the null terminator */
+   namelen = strlen(data->resource_name) + strlen(pmic_id) - 1;
+   name = devm_kzalloc(dev, namelen, GFP_KERNEL);
+   ret = snprintf(name, namelen, data->resource_name, pmic_id);
+   if (ret < 0 || ret >= namelen) {
+   dev_err(dev, "Failed to create RPMh regulator name\n");
return -ENOMEM;
}
 
-   ret = rpmh_regulator_init_vreg(vreg, dev, node,

[PATCH v5 19/23] power: regulator: qcom-rpmh-regulator: remove unused regulators

2024-07-11 Thread Caleb Connolly
Initially just include the few regulators needed for the RB5 board.
Others can be added back as-needed.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 1281 -
 1 file changed, 1281 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 089623f3a2b9..2a8e8f9ac444 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -338,68 +338,8 @@ static unsigned int rpmh_regulator_vrm_get_mode(struct 
regulator_dev *rdev)
 
return vreg->mode;
 }
 
-/**
- * rpmh_regulator_vrm_get_optimum_mode() - get the mode based on the  load
- * @rdev:  Regulator device pointer for the rpmh-regulator
- * @input_uV:  Input voltage
- * @output_uV: Output voltage
- * @load_uA:   Aggregated load current in microamps
- *
- * This function is used in the regulator_ops for VRM type RPMh regulator
- * devices.
- *
- * Return: 0 on success, errno on failure
- */
-static unsigned int rpmh_regulator_vrm_get_optimum_mode(
-   struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-
-   if (load_uA >= vreg->hw_data->hpm_min_load_uA)
-   return REGULATOR_MODE_NORMAL;
-   else
-   return REGULATOR_MODE_IDLE;
-}
-
-static int rpmh_regulator_vrm_set_bypass(struct regulator_dev *rdev,
-   bool enable)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-   int ret;
-
-   if (vreg->bypassed == enable)
-   return 0;
-
-   ret = rpmh_regulator_vrm_set_mode_bypass(vreg, vreg->mode, enable);
-   if (!ret)
-   vreg->bypassed = enable;
-
-   return ret;
-}
-
-static int rpmh_regulator_vrm_get_bypass(struct regulator_dev *rdev,
-   bool *enable)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-
-   *enable = vreg->bypassed;
-
-   return 0;
-}
-
-static const struct regulator_ops rpmh_regulator_vrm_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-   .set_voltage_sel= rpmh_regulator_vrm_set_voltage_sel,
-   .get_voltage_sel= rpmh_regulator_vrm_get_voltage_sel,
-   .list_voltage   = regulator_list_voltage_linear_range,
-   .set_mode   = rpmh_regulator_vrm_set_mode,
-   .get_mode   = rpmh_regulator_vrm_get_mode,
-};
-
 static const struct regulator_ops rpmh_regulator_vrm_drms_ops = {
.enable = rpmh_regulator_enable,
.disable= rpmh_regulator_disable,
.is_enabled = rpmh_regulator_is_enabled,
@@ -410,331 +350,8 @@ static const struct regulator_ops 
rpmh_regulator_vrm_drms_ops = {
.get_mode   = rpmh_regulator_vrm_get_mode,
.get_optimum_mode   = rpmh_regulator_vrm_get_optimum_mode,
 };
 
-static const struct regulator_ops rpmh_regulator_vrm_bypass_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-   .set_voltage_sel= rpmh_regulator_vrm_set_voltage_sel,
-   .get_voltage_sel= rpmh_regulator_vrm_get_voltage_sel,
-   .list_voltage   = regulator_list_voltage_linear_range,
-   .set_mode   = rpmh_regulator_vrm_set_mode,
-   .get_mode   = rpmh_regulator_vrm_get_mode,
-   .set_bypass = rpmh_regulator_vrm_set_bypass,
-   .get_bypass = rpmh_regulator_vrm_get_bypass,
-};
-
-static const struct regulator_ops rpmh_regulator_xob_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-};
-
-/**
- * rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator
- * @vreg:  Pointer to the individual rpmh-regulator resource
- * @dev:   Pointer to the top level rpmh-regulator PMIC 
device
- * @node:  Pointer to the individual rpmh-regulator resource
- * device node
- * @pmic_id:   String used to identify the top level rpmh-regulator
- * PMIC device on the board
- * @pmic_rpmh_data:Pointer to a null-terminated array of rpmh-regulator
- * resources defined for the top level PMIC device
- *
- * Return: 0 on success, errno on failure
- */
-static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
-   struct device_node *node, const char *pmic_id,
-

[PATCH v5 20/23] power: regulator: qcom-rpmh-regulator: port ops to U-Boot

2024-07-11 Thread Caleb Connolly
Port over the regulator ops to U-Boot's regulator API. Add back the
pmic5 mode map using U-Boot dm_regulator_mode API and adjust the
pmic5_pldo and pmic5_pldo_lv definitions. No functional changes.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 158 ++
 1 file changed, 87 insertions(+), 71 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 2a8e8f9ac444..b716b380c148 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -192,87 +192,96 @@ struct rpmh_vreg_init_data {
  *
  * Return: 0 on success, errno on failure
  */
 static int rpmh_regulator_send_request(struct rpmh_vreg *vreg,
-   struct tcs_cmd *cmd, bool wait_for_ack)
+  const struct tcs_cmd *cmd, bool 
wait_for_ack)
 {
int ret;
 
if (wait_for_ack || vreg->always_wait_for_ack)
-   ret = rpmh_write(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, 1);
+   ret = rpmh_write(vreg->dev->parent, RPMH_ACTIVE_ONLY_STATE, 
cmd, 1);
else
-   ret = rpmh_write_async(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd,
-   1);
+   ret = rpmh_write_async(vreg->dev->parent, 
RPMH_ACTIVE_ONLY_STATE, cmd, 1);
 
return ret;
 }
 
-static int _rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev,
-   unsigned int selector, bool wait_for_ack)
+static int _rpmh_regulator_vrm_set_value(struct udevice *rdev,
+int uv, bool wait_for_ack)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
struct tcs_cmd cmd = {
.addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE,
};
int ret;
+   unsigned int selector;
 
-   /* VRM voltage control register is set with voltage in millivolts. */
-   cmd.data = DIV_ROUND_UP(regulator_list_voltage_linear_range(rdev,
-   selector), 1000);
+   selector = (uv - vreg->hw_data->voltage_range.min) / 
vreg->hw_data->voltage_range.step;
+   cmd.data = DIV_ROUND_UP(vreg->hw_data->voltage_range.min +
+   selector * vreg->hw_data->voltage_range.step, 
1000);
 
ret = rpmh_regulator_send_request(vreg, , wait_for_ack);
if (!ret)
-   vreg->voltage_selector = selector;
+   vreg->uv = cmd.data * 1000;
 
return ret;
 }
 
-static int rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev,
-   unsigned int selector)
+static int rpmh_regulator_vrm_set_value(struct udevice *rdev,
+   int uv)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
+
+   debug("%s: set_value %d (current %d)\n", rdev->name, uv, vreg->uv);
 
if (vreg->enabled == -EINVAL) {
/*
 * Cache the voltage and send it later when the regulator is
 * enabled or disabled.
 */
-   vreg->voltage_selector = selector;
+   vreg->uv = uv;
return 0;
}
 
-   return _rpmh_regulator_vrm_set_voltage_sel(rdev, selector,
-   selector > vreg->voltage_selector);
+   return _rpmh_regulator_vrm_set_value(rdev, uv,
+   uv > vreg->uv);
 }
 
-static int rpmh_regulator_vrm_get_voltage_sel(struct regulator_dev *rdev)
+static int rpmh_regulator_vrm_get_value(struct udevice *rdev)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
 
-   return vreg->voltage_selector;
+   debug("%s: get_value %d\n", rdev->name, vreg->uv);
+
+   return vreg->uv;
 }
 
-static int rpmh_regulator_is_enabled(struct regulator_dev *rdev)
+static int rpmh_regulator_is_enabled(struct udevice *rdev)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
 
-   return vreg->enabled;
+   debug("%s: is_enabled %d\n", rdev->name, vreg->enabled);
+
+   return vreg->enabled > 0;
 }
 
-static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev,
-   bool enable)
+static int rpmh_regulator_set_enable_state(struct udevice *rdev,
+  bool enable)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
struct tcs_cmd cmd = {
 

[PATCH v5 18/23] power: regulator: qcom-rpmh-regulator: adjust structs for U-Boot

2024-07-11 Thread Caleb Connolly
Switch to our linear_range helpers and remove unused/unsupported
linux-isms.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 28 +--
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index d0acee9f558e..089623f3a2b9 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -102,13 +102,12 @@ struct linear_range {
  * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
  * @regulator_type:RPMh accelerator type used to manage this
  * regulator
  * @ops:   Pointer to regulator ops callback structure
- * @voltage_ranges:The possible ranges of voltages supported by 
this
- * PMIC regulator type
- * @n_linear_ranges:   Number of entries in voltage_ranges
+ * @voltage_range: The single range of voltages supported by this
+ * PMIC regulator type
  * @n_voltages:The number of unique voltage set points 
defined
- * by voltage_ranges
+ * by voltage_range
  * @hpm_min_load_uA:   Minimum load current in microamps that requires
  * high power mode (HPM) operation.  This is used
  * for LDO hardware type regulators only.
  * @pmic_mode_map: Array indexed by regulator framework mode
@@ -119,15 +118,15 @@ struct linear_range {
  * in device tree to a regulator framework mode
  */
 struct rpmh_vreg_hw_data {
enum rpmh_regulator_typeregulator_type;
-   const struct regulator_ops  *ops;
-   const struct linear_range   *voltage_ranges;
-   int n_linear_ranges;
+   const struct dm_regulator_ops   *ops;
+   struct linear_range voltage_range;
int n_voltages;
int hpm_min_load_uA;
-   const int   *pmic_mode_map;
-   unsigned int  (*of_map_mode)(unsigned int mode);
+   struct dm_regulator_mode*pmic_mode_map;
+   int n_modes;
+   unsigned int(*of_map_mode)(unsigned int 
mode);
 };
 
 /**
  * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a
@@ -148,23 +147,22 @@ struct rpmh_vreg_hw_data {
  * not
  * @bypassed:  Boolean indicating if the regulator is in
  * bypass (pass-through) mode or not.  This is
  * only used by BOB rpmh-regulator resources.
- * @voltage_selector:  Selector used for get_voltage_sel() and
- * set_voltage_sel() callbacks
+ * @uv:Selector used for get_voltage_sel() and
+ * set_value() callbacks
  * @mode:  RPMh VRM regulator current framework mode
  */
 struct rpmh_vreg {
-   struct device   *dev;
+   struct udevice  *dev;
u32 addr;
-   struct regulator_desc   rdesc;
const struct rpmh_vreg_hw_data  *hw_data;
boolalways_wait_for_ack;
 
int enabled;
boolbypassed;
-   int voltage_selector;
-   unsigned intmode;
+   int uv;
+   int mode;
 };
 
 /**
  * struct rpmh_vreg_init_data - initialization data for an RPMh regulator

-- 
2.45.2



[PATCH v5 13/23] soc: qcom: rpmh: U-Boot API changes

2024-07-11 Thread Caleb Connolly
Fix build errors, add some debug logging.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 53 +++--
 include/soc/qcom/rpmh.h |  4 ++--
 2 files changed, 22 insertions(+), 35 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 22605e0291a1..96f14a9afdf2 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -15,27 +15,30 @@
 #include "rpmh-internal.h"
 
 #define RPMH_TIMEOUT_MSmsecs_to_jiffies(1)
 
-#define DEFINE_RPMH_MSG_ONSTACK(device, s, q, name)\
+#define DEFINE_RPMH_MSG_ONSTACK(device, s, name)   \
struct rpmh_request name = {\
.msg = {\
.state = s, \
.cmds = name.cmd,   \
.num_cmds = 0,  \
-   .wait_for_compl = true, \
},  \
.cmd = { { 0 } },   \
-   .completion = q,\
.dev = device,  \
-   .needs_free = false,\
+   .needs_free = false,\
}
 
 #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
 
-static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
+static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct udevice *dev)
 {
-   struct rsc_drv *drv = dev_get_drvdata(dev->parent);
+   struct rsc_drv *drv = (struct rsc_drv *)dev_get_priv(dev->parent);
+
+   if (!drv) {
+   log_err("BUG: no RPMh driver for %s (parent %s)\n", dev->name, 
dev->parent->name);
+   BUG();
+   }
 
return >client;
 }
 
@@ -49,36 +52,23 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct 
device *dev)
  * Cache the RPMH request and send if the state is ACTIVE_ONLY.
  * SLEEP/WAKE_ONLY requests are not sent to the controller at
  * this time. Use rpmh_flush() to send them to the controller.
  */
-static int __rpmh_write(const struct device *dev, enum rpmh_state state,
+static int __rpmh_write(const struct udevice *dev, enum rpmh_state state,
struct rpmh_request *rpm_msg)
 {
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
-   int ret = -EINVAL;
-   struct cache_req *req;
-   int i;
 
-   /* Cache the request in our store and link the payload */
-   for (i = 0; i < rpm_msg->msg.num_cmds; i++) {
-   req = cache_rpm_request(ctrlr, state, _msg->msg.cmds[i]);
-   if (IS_ERR(req))
-   return PTR_ERR(req);
+   if (state != RPMH_ACTIVE_ONLY_STATE) {
+   log_err("only ACTIVE_ONLY state supported\n");
+   return -EINVAL;
}
 
-   if (state == RPMH_ACTIVE_ONLY_STATE) {
-   ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), _msg->msg);
-   } else {
-   /* Clean up our call by spoofing tx_done */
-   ret = 0;
-   rpmh_tx_done(_msg->msg);
-   }
-
-   return ret;
+   return rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), _msg->msg);
 }
 
 static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
-   const struct tcs_cmd *cmd, u32 n)
+  const struct tcs_cmd *cmd, u32 n)
 {
if (!cmd || !n || n > MAX_RPMH_PAYLOAD)
return -EINVAL;
 
@@ -87,8 +77,10 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
req->msg.state = state;
req->msg.cmds = req->cmd;
req->msg.num_cmds = n;
 
+   debug("rpmh_msg: %d, %d cmds [first %#x/%#x]\n", state, n, cmd->addr, 
cmd->data);
+
return 0;
 }
 
 /**
@@ -100,24 +92,19 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
  * @n: The number of elements in @cmd
  *
  * May sleep. Do not call from atomic contexts.
  */
-int rpmh_write(const struct device *dev, enum rpmh_state state,
+int rpmh_write(const struct udevice *dev, enum rpmh_state state,
   const struct tcs_cmd *cmd, u32 n)
 {
-   DECLARE_COMPLETION_ONSTACK(compl);
-   DEFINE_RPMH_MSG_ONSTACK(dev, state, , rpm_msg);
+   DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg);
int ret;
 
ret = __fill_rpmh_msg(_msg, state, cmd, n);
if (ret)
return ret;
 
ret = __rpmh_write(dev, state, _msg);
-   if (ret)
-   return ret;
 
-   ret = wait_for_completion_timeout(, RPMH_TIMEOUT_MS);
-   WARN_ON(!ret);
-   return (ret > 0) ? 0 : -ETIMEDOUT;
+   return ret;
 }
 EXPORT_SYMBOL_GPL(rpmh_write);
diff --git a/include/soc/qcom/rpmh.h b

[PATCH v5 17/23] power: regulator: qcom-rpmh-regulator: port over lineage_range helpers

2024-07-11 Thread Caleb Connolly
Import struct linear_range() and builder macro from Linux regulator
core.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 37 +++
 1 file changed, 37 insertions(+)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 5f522de44734..d0acee9f558e 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -28,8 +28,15 @@ enum rpmh_regulator_type {
VRM,
XOB,
 };
 
+enum rpmh_regulator_mode {
+   REGULATOR_MODE_RETENTION,
+   REGULATOR_MODE_LPM,
+   REGULATOR_MODE_AUTO,
+   REGULATOR_MODE_HPM,
+};
+
 #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0
 #define RPMH_REGULATOR_REG_ENABLE  0x4
 #define RPMH_REGULATOR_REG_VRM_MODE0x8
 
@@ -60,8 +67,38 @@ enum rpmh_regulator_type {
 #define PMIC5_BOB_MODE_PFM 4
 #define PMIC5_BOB_MODE_AUTO6
 #define PMIC5_BOB_MODE_PWM 7
 
+
+/**
+ * struct linear_range - table of selector - value pairs
+ *
+ * Define a lookup-table for range of values. Intended to help when looking
+ * for a register value matching certaing physical measure (like voltage).
+ * Usable when increment of one in register always results a constant increment
+ * of the physical measure (like voltage).
+ *
+ * @min:  Lowest value in range
+ * @min_sel: Lowest selector for range
+ * @max_sel: Highest selector for range
+ * @step: Value step size
+ */
+struct linear_range {
+   unsigned int min;
+   unsigned int min_sel;
+   unsigned int max_sel;
+   unsigned int step;
+};
+
+/* Initialize struct linear_range for regulators */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)  \
+{  \
+   .min= _min_uV,  \
+   .min_sel= _min_sel, \
+   .max_sel= _max_sel, \
+   .step   = _step_uV, \
+}
+
 /**
  * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
  * @regulator_type:RPMh accelerator type used to manage this
  * regulator

-- 
2.45.2



[PATCH v5 15/23] power: regulator: import qcom-rpmh-regulator from Linux

2024-07-11 Thread Caleb Connolly
Import the driver from Linux 6.10-rc6.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 1709 +
 1 file changed, 1709 insertions(+)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
new file mode 100644
index ..80e304711345
--- /dev/null
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -0,0 +1,1709 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+// Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+
+/**
+ * enum rpmh_regulator_type - supported RPMh accelerator types
+ * @VRM:   RPMh VRM accelerator which supports voting on enable, voltage,
+ * and mode of LDO, SMPS, and BOB type PMIC regulators.
+ * @XOB:   RPMh XOB accelerator which supports voting on the enable state
+ * of PMIC regulators.
+ */
+enum rpmh_regulator_type {
+   VRM,
+   XOB,
+};
+
+#define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0
+#define RPMH_REGULATOR_REG_ENABLE  0x4
+#define RPMH_REGULATOR_REG_VRM_MODE0x8
+
+#define PMIC4_LDO_MODE_RETENTION   4
+#define PMIC4_LDO_MODE_LPM 5
+#define PMIC4_LDO_MODE_HPM 7
+
+#define PMIC4_SMPS_MODE_RETENTION  4
+#define PMIC4_SMPS_MODE_PFM5
+#define PMIC4_SMPS_MODE_AUTO   6
+#define PMIC4_SMPS_MODE_PWM7
+
+#define PMIC4_BOB_MODE_PASS0
+#define PMIC4_BOB_MODE_PFM 1
+#define PMIC4_BOB_MODE_AUTO2
+#define PMIC4_BOB_MODE_PWM 3
+
+#define PMIC5_LDO_MODE_RETENTION   3
+#define PMIC5_LDO_MODE_LPM 4
+#define PMIC5_LDO_MODE_HPM 7
+
+#define PMIC5_SMPS_MODE_RETENTION  3
+#define PMIC5_SMPS_MODE_PFM4
+#define PMIC5_SMPS_MODE_AUTO   6
+#define PMIC5_SMPS_MODE_PWM7
+
+#define PMIC5_BOB_MODE_PASS2
+#define PMIC5_BOB_MODE_PFM 4
+#define PMIC5_BOB_MODE_AUTO6
+#define PMIC5_BOB_MODE_PWM 7
+
+/**
+ * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
+ * @regulator_type:RPMh accelerator type used to manage this
+ * regulator
+ * @ops:   Pointer to regulator ops callback structure
+ * @voltage_ranges:The possible ranges of voltages supported by 
this
+ * PMIC regulator type
+ * @n_linear_ranges:   Number of entries in voltage_ranges
+ * @n_voltages:The number of unique voltage set points 
defined
+ * by voltage_ranges
+ * @hpm_min_load_uA:   Minimum load current in microamps that requires
+ * high power mode (HPM) operation.  This is used
+ * for LDO hardware type regulators only.
+ * @pmic_mode_map: Array indexed by regulator framework mode
+ * containing PMIC hardware modes.  Must be large
+ * enough to index all framework modes supported
+ * by this regulator hardware type.
+ * @of_map_mode:   Maps an RPMH_REGULATOR_MODE_* mode value defined
+ * in device tree to a regulator framework mode
+ */
+struct rpmh_vreg_hw_data {
+   enum rpmh_regulator_typeregulator_type;
+   const struct regulator_ops  *ops;
+   const struct linear_range   *voltage_ranges;
+   int n_linear_ranges;
+   int n_voltages;
+   int hpm_min_load_uA;
+   const int   *pmic_mode_map;
+   unsigned int  (*of_map_mode)(unsigned int mode);
+};
+
+/**
+ * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a
+ * single regulator device
+ * @dev:   Device pointer for the top-level PMIC RPMh
+ * regulator parent device.  This is used as a
+ * handle in RPMh write requests.
+ * @addr:  Base address of the regulator resource within
+ * an RPMh accelerator
+ * @rdesc: Regulator descriptor
+ * @hw_data:   PMIC regulator configuration data for

[PATCH v5 16/23] power: regulator: qcom-rpmh-regulator: adjust headers for U-Boot

2024-07-11 Thread Caleb Connolly
Remove unused/unsupported Linux headers and add necessary U-Boot ones.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 80e304711345..5f522de44734 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -4,17 +4,14 @@
 
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
 

-- 
2.45.2



[PATCH v5 12/23] soc: qcom: rpmh: drop unused functions

2024-07-11 Thread Caleb Connolly
A lot of the features in here are only relevant when running
multi-threaded with interrupts. Drop everything except what we need to
run single-threaded with a single TCS (which is all the rpmh-rsc
framework in U-Boot supports).

Keep rpmh_write_async() for simplicity and make it wrap the regular
rpmh_write().

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 371 
 include/soc/qcom/rpmh.h |  25 +---
 2 files changed, 3 insertions(+), 393 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 03ef4106c9a6..22605e0291a1 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -31,124 +31,15 @@
}
 
 #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
 
-/**
- * struct cache_req: the request object for caching
- *
- * @addr: the address of the resource
- * @sleep_val: the sleep vote
- * @wake_val: the wake vote
- * @list: linked list obj
- */
-struct cache_req {
-   u32 addr;
-   u32 sleep_val;
-   u32 wake_val;
-   struct list_head list;
-};
-
-/**
- * struct batch_cache_req - An entry in our batch catch
- *
- * @list: linked list obj
- * @count: number of messages
- * @rpm_msgs: the messages
- */
-
-struct batch_cache_req {
-   struct list_head list;
-   int count;
-   struct rpmh_request rpm_msgs[];
-};
-
 static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
 {
struct rsc_drv *drv = dev_get_drvdata(dev->parent);
 
return >client;
 }
 
-void rpmh_tx_done(const struct tcs_request *msg)
-{
-   struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
-   msg);
-   struct completion *compl = rpm_msg->completion;
-   bool free = rpm_msg->needs_free;
-
-   if (!compl)
-   goto exit;
-
-   /* Signal the blocking thread we are done */
-   complete(compl);
-
-exit:
-   if (free)
-   kfree(rpm_msg);
-}
-
-static struct cache_req *__find_req(struct rpmh_ctrlr *ctrlr, u32 addr)
-{
-   struct cache_req *p, *req = NULL;
-
-   list_for_each_entry(p, >cache, list) {
-   if (p->addr == addr) {
-   req = p;
-   break;
-   }
-   }
-
-   return req;
-}
-
-static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr,
-  enum rpmh_state state,
-  struct tcs_cmd *cmd)
-{
-   struct cache_req *req;
-   unsigned long flags;
-   u32 old_sleep_val, old_wake_val;
-
-   spin_lock_irqsave(>cache_lock, flags);
-   req = __find_req(ctrlr, cmd->addr);
-   if (req)
-   goto existing;
-
-   req = kzalloc(sizeof(*req), GFP_ATOMIC);
-   if (!req) {
-   req = ERR_PTR(-ENOMEM);
-   goto unlock;
-   }
-
-   req->addr = cmd->addr;
-   req->sleep_val = req->wake_val = UINT_MAX;
-   list_add_tail(>list, >cache);
-
-existing:
-   old_sleep_val = req->sleep_val;
-   old_wake_val = req->wake_val;
-
-   switch (state) {
-   case RPMH_ACTIVE_ONLY_STATE:
-   case RPMH_WAKE_ONLY_STATE:
-   req->wake_val = cmd->data;
-   break;
-   case RPMH_SLEEP_STATE:
-   req->sleep_val = cmd->data;
-   break;
-   }
-
-   ctrlr->dirty |= (req->sleep_val != old_sleep_val ||
-req->wake_val != old_wake_val) &&
-req->sleep_val != UINT_MAX &&
-req->wake_val != UINT_MAX;
-
-unlock:
-   spin_unlock_irqrestore(>cache_lock, flags);
-
-   return req;
-}
-
 /**
  * __rpmh_write: Cache and send the RPMH request
  *
  * @dev: The device making the request
@@ -199,40 +90,8 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
 
return 0;
 }
 
-/**
- * rpmh_write_async: Write a set of RPMH commands
- *
- * @dev: The device making the request
- * @state: Active/sleep set
- * @cmd: The payload data
- * @n: The number of elements in payload
- *
- * Write a set of RPMH commands, the order of commands is maintained
- * and will be sent as a single shot.
- */
-int rpmh_write_async(const struct device *dev, enum rpmh_state state,
-const struct tcs_cmd *cmd, u32 n)
-{
-   struct rpmh_request *rpm_msg;
-   int ret;
-
-   rpm_msg = kzalloc(sizeof(*rpm_msg), GFP_ATOMIC);
-   if (!rpm_msg)
-   return -ENOMEM;
-   rpm_msg->needs_free = true;
-
-   ret = __fill_rpmh_msg(rpm_msg, state, cmd, n);
-   if (ret) {
-   kfree(rpm_msg);
-   return ret;
-   }
-
-   return __rpmh_write(dev, state, rpm_msg);
-}
-EXPORT_SYMBOL_GPL(rpmh_write_async);
-
 /**
  * rpmh_write: 

[PATCH v5 14/23] soc: qcom: add build infrastructure

2024-07-11 Thread Caleb Connolly
Add Kconfig / Makefiles to build rpmh and cmd-db drivers.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/Kconfig   |  1 +
 drivers/soc/Makefile  |  1 +
 drivers/soc/qcom/Kconfig  | 27 +++
 drivers/soc/qcom/Makefile |  4 
 4 files changed, 33 insertions(+)

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cee506fe4747..8ef408d9ba1b 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -47,8 +47,9 @@ config SOC_XILINX_VERSAL_NET
  Enable this option to select SoC device id driver for Xilinx Versal 
NET.
  This allows other drivers to verify the SoC familiy & revision using
  matching SoC attributes.
 
+source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/samsung/Kconfig"
 source "drivers/soc/ti/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ec89a053165..00e6a5ac8e2b 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,8 +2,9 @@
 #
 # Makefile for the U-Boot SOC specific device drivers.
 
 obj-$(CONFIG_SOC_AMD_VERSAL2) += soc_amd_versal2.o
+obj-$(CONFIG_SOC_QCOM) += qcom/
 obj-$(CONFIG_SOC_SAMSUNG) += samsung/
 obj-$(CONFIG_SOC_TI) += ti/
 obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
 obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
new file mode 100644
index ..4aa7833930c7
--- /dev/null
+++ b/drivers/soc/qcom/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# QCOM Soc drivers
+#
+menuconfig SOC_QCOM
+   bool "Qualcomm SOC drivers support"
+   help
+ Say Y here if you want to enable Qualcomm SOC drivers support.
+
+if SOC_QCOM
+
+config QCOM_COMMAND_DB
+   bool "Qualcomm Command DB"
+   help
+ Command DB queries shared memory by key string for shared system
+ resources. Platform drivers that require to set state of a shared
+ resource on a RPM-hardened platform must use this database to get
+ SoC specific identifier and information for the shared resources.
+
+config QCOM_RPMH
+   bool "Qualcomm RPMh support"
+   depends on QCOM_COMMAND_DB
+   help
+ Say y here to support the Qualcomm RPMh (resource peripheral manager)
+ if you need to control regulators on Qualcomm platforms, say y here.
+
+endif # SOC_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
new file mode 100644
index ..78fae8bbfa16
--- /dev/null
+++ b/drivers/soc/qcom/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_QCOM_RPMH) += rpmh-rsc.o rpmh.o

-- 
2.45.2



[PATCH v5 11/23] soc: qcom: rpmh: adjust headers for U-Boot

2024-07-11 Thread Caleb Connolly
Drop unused/unsupported Linux headers and add dm/device.h for U-Boot.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 8903ed956312..03ef4106c9a6 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -2,22 +2,14 @@
 /*
  * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  */
 
-#include 
+#include 
+#include 
 #include 
-#include 
-#include 
 #include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
 #include 
-#include 
 
 #include 
 
 #include "rpmh-internal.h"

-- 
2.45.2



[PATCH v5 10/23] soc: qcom: rpmh-rsc: remaining U-Boot API changes

2024-07-11 Thread Caleb Connolly
Minor adjustments to fix building with U-Boot and work correctly as a
synchronous driver without interrupts. RPMh is fast enough that we can
get away with just firing off requests and assuming they complete.

U-Boot behaviour changes are annotated with a "U-Boot:" comment.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-rsc.c | 78 +
 1 file changed, 29 insertions(+), 49 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index d4ef88dda184..566fa16baba9 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -134,16 +134,8 @@ enum {
  *  |  ..   |
  *  +---+
  */
 
-#define USECS_TO_CYCLES(time_usecs)\
-   xloops_to_cycles((time_usecs) * 0x10C7UL)
-
-static inline unsigned long xloops_to_cycles(u64 xloops)
-{
-   return (xloops * loops_per_jiffy * HZ) >> 32;
-}
-
 static u32 rpmh_rsc_reg_offset_ver_2_7[] = {
[RSC_DRV_TCS_OFFSET]= 672,
[RSC_DRV_CMD_OFFSET]= 20,
[DRV_SOLVER_CONFIG] = 0x04,
@@ -248,37 +240,18 @@ static void write_tcs_reg_sync(const struct rsc_drv *drv, 
int reg, int tcs_id,
  */
 static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv,
 const struct tcs_request *msg)
 {
-   int type;
-   struct tcs_group *tcs;
-
-   switch (msg->state) {
-   case RPMH_ACTIVE_ONLY_STATE:
-   type = ACTIVE_TCS;
-   break;
-   case RPMH_WAKE_ONLY_STATE:
-   type = WAKE_TCS;
-   break;
-   case RPMH_SLEEP_STATE:
-   type = SLEEP_TCS;
-   break;
-   default:
+   /*
+* U-Boot: since we're single threaded and running synchronously we can
+* just always used the first active TCS.
+*/
+   if (msg->state != RPMH_ACTIVE_ONLY_STATE) {
+   log_err("WARN: only ACTIVE_ONLY state supported\n");
return ERR_PTR(-EINVAL);
}
 
-   /*
-* If we are making an active request on a RSC that does not have a
-* dedicated TCS for active state use, then re-purpose a wake TCS to
-* send active votes. This is safe because we ensure any active-only
-* transfers have finished before we use it (maybe by running from
-* the last CPU in PM code).
-*/
-   tcs = >tcs[type];
-   if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs)
-   tcs = >tcs[WAKE_TCS];
-
-   return tcs;
+   return >tcs[ACTIVE_TCS];
 }
 
 /**
  * __tcs_buffer_write() - Write to TCS hardware from a request; don't trigger.
@@ -298,11 +271,8 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
u32 cmd_enable = 0;
struct tcs_cmd *cmd;
int i, j;
 
-   /* Convert all commands to RR when the request has wait_for_compl set */
-   cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0;
-
for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) {
cmd = >cmds[i];
cmd_enable |= BIT(j);
msgid = cmd_msgid;
@@ -314,9 +284,11 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
 
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, 
msgid);
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, 
cmd->addr);
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, 
cmd->data);
-   trace_rpmh_send_msg(drv, tcs_id, msg->state, j, msgid, cmd);
+   debug("tcs(m): %d [%s] cmd(n): %d msgid: %#x addr: %#x data: 
%#x complete: %d\n",
+ tcs_id, msg->state == RPMH_ACTIVE_ONLY_STATE ? "active" : 
"?", j, msgid,
+ cmd->addr, cmd->data, cmd->wait);
}
 
cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id);
write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable);
@@ -346,34 +318,28 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
  */
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
 {
struct tcs_group *tcs;
-   int tcs_id;
-
-   might_sleep();
+   int tcs_id, i;
+   u32 addr;
 
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
 
-   spin_lock_irq(>lock);
-
-   /* Wait forever for a free tcs. It better be there eventually! */
-   wait_event_lock_irq(drv->tcs_wait,
-   (tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
-   drv->lock);
+   /* u-boot is s

[PATCH v5 09/23] soc: qcom: rpmh-rsc: adjust probe for U-Boot

2024-07-11 Thread Caleb Connolly
Rework the rpmh-rsc initialization to use U-Boot's driver model and
initialize cmd-db.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-internal.h |  14 ++--
 drivers/soc/qcom/rpmh-rsc.c  | 143 +--
 2 files changed, 50 insertions(+), 107 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
index 12c5b8d9cf86..ac8f6c35a7a4 100644
--- a/drivers/soc/qcom/rpmh-internal.h
+++ b/drivers/soc/qcom/rpmh-internal.h
@@ -7,17 +7,18 @@
 #ifndef __RPM_INTERNAL_H__
 #define __RPM_INTERNAL_H__
 
 #include 
-#include 
 #include 
 
 #define TCS_TYPE_NR4
 #define MAX_CMDS_PER_TCS   16
 #define MAX_TCS_PER_TYPE   3
 #define MAX_TCS_NR (MAX_TCS_PER_TYPE * TCS_TYPE_NR)
 #define MAX_TCS_SLOTS  (MAX_CMDS_PER_TCS * MAX_TCS_PER_TYPE)
 
+#define USEC_PER_SEC   100UL
+
 struct rsc_drv;
 
 /**
  * struct tcs_group: group of Trigger Command Sets (TCS) to send state requests
@@ -63,10 +64,9 @@ struct tcs_group {
  */
 struct rpmh_request {
struct tcs_request msg;
struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
-   struct completion *completion;
-   const struct device *dev;
+   const struct udevice *dev;
bool needs_free;
 };
 
 /**
@@ -78,9 +78,8 @@ struct rpmh_request {
  * @batch_cache: Cache sleep and wake requests sent as batch
  */
 struct rpmh_ctrlr {
struct list_head cache;
-   spinlock_t cache_lock;
bool dirty;
struct list_head batch_cache;
 };
 
@@ -122,17 +121,12 @@ struct rsc_drv {
void __iomem *base;
void __iomem *tcs_base;
int id;
int num_tcs;
-   struct notifier_block rsc_pm;
-   struct notifier_block genpd_nb;
-   atomic_t cpus_in_pm;
struct tcs_group tcs[TCS_TYPE_NR];
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
-   spinlock_t lock;
-   wait_queue_head_t tcs_wait;
struct rpmh_ctrlr client;
-   struct device *dev;
+   struct udevice *dev;
struct rsc_ver ver;
u32 *regs;
 };
 
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index c09214552cfb..d4ef88dda184 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -386,20 +386,20 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct 
tcs_request *msg)
 
return 0;
 }
 
-static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv 
*drv)
+static int rpmh_probe_tcs_config(struct udevice *dev, struct rsc_drv *drv)
 {
struct tcs_type_config {
u32 type;
u32 n;
} tcs_cfg[TCS_TYPE_NR] = { { 0 } };
-   struct device_node *dn = pdev->dev.of_node;
+   ofnode dn = dev_ofnode(dev);
u32 config, max_tcs, ncpt, offset;
int i, ret, n, st = 0;
struct tcs_group *tcs;
 
-   ret = of_property_read_u32(dn, "qcom,tcs-offset", );
+   ret = ofnode_read_u32(dn, "qcom,tcs-offset", );
if (ret)
return ret;
drv->tcs_base = drv->base + offset;
 
@@ -411,24 +411,15 @@ static int rpmh_probe_tcs_config(struct platform_device 
*pdev, struct rsc_drv *d
 
ncpt = config & (DRV_NCPT_MASK << DRV_NCPT_SHIFT);
ncpt = ncpt >> DRV_NCPT_SHIFT;
 
-   n = of_property_count_u32_elems(dn, "qcom,tcs-config");
-   if (n != 2 * TCS_TYPE_NR)
-   return -EINVAL;
+   n = ofnode_read_u32_array(dn, "qcom,tcs-config", (u32 *)tcs_cfg, 2 * 
TCS_TYPE_NR);
+   if (n < 0) {
+   log_err("RPMh: %s: error reading qcom,tcs-config %d\n", 
dev->name, n);
+   return n;
+   }
 
for (i = 0; i < TCS_TYPE_NR; i++) {
-   ret = of_property_read_u32_index(dn, "qcom,tcs-config",
-i * 2, _cfg[i].type);
-   if (ret)
-   return ret;
-   if (tcs_cfg[i].type >= TCS_TYPE_NR)
-   return -EINVAL;
-
-   ret = of_property_read_u32_index(dn, "qcom,tcs-config",
-i * 2 + 1, _cfg[i].n);
-   if (ret)
-   return ret;
if (tcs_cfg[i].n > MAX_TCS_PER_TYPE)
return -EINVAL;
}
 
@@ -457,43 +448,39 @@ static int rpmh_probe_tcs_config(struct platform_device 
*pdev, struct rsc_drv *d
 
return 0;
 }
 
-static int rpmh_rsc_probe(struct platform_device *pdev)
+static int rpmh_rsc_bind(struct udevice *dev)
 {
-   struct device_node *dn = pdev->dev.of_node;
-   struct rsc_drv *drv;
-   char drv_id[10] = {0};
-   int ret, irq;
-   u32 solver_config;
-   u32 rsc_id;
+   int ret;
 
-   /*
-* Even though RPMh doesn't d

[PATCH v5 07/23] soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS support

2024-07-11 Thread Caleb Connolly
Since U-Boot is single threaded, we can avoid most of the complexity
that comes with handling more than one in-flight TCS. Drop all the rpmh
code associated with multi-threading as we'll instead wait for a
response on each TCS.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-internal.h |   4 -
 drivers/soc/qcom/rpmh-rsc.c  | 562 ---
 2 files changed, 566 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
index e3cf1beff803..12c5b8d9cf86 100644
--- a/drivers/soc/qcom/rpmh-internal.h
+++ b/drivers/soc/qcom/rpmh-internal.h
@@ -139,10 +139,6 @@ struct rsc_drv {
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg);
 int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
 const struct tcs_request *msg);
 void rpmh_rsc_invalidate(struct rsc_drv *drv);
-void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv);
-
-void rpmh_tx_done(const struct tcs_request *msg);
-int rpmh_flush(struct rpmh_ctrlr *ctrlr);
 
 #endif /* __RPM_INTERNAL_H__ */
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index de86009ecd91..fc8321bf208f 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -246,49 +246,8 @@ static void write_tcs_reg_sync(const struct rsc_drv *drv, 
int reg, int tcs_id,
pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
   data, tcs_id, reg);
 }
 
-/**
- * tcs_invalidate() - Invalidate all TCSes of the given type (sleep or wake).
- * @drv:  The RSC controller.
- * @type: SLEEP_TCS or WAKE_TCS
- *
- * This will clear the "slots" variable of the given tcs_group and also
- * tell the hardware to forget about all entries.
- *
- * The caller must ensure that no other RPMH actions are happening when this
- * function is called, since otherwise the device may immediately become
- * used again even before this function exits.
- */
-static void tcs_invalidate(struct rsc_drv *drv, int type)
-{
-   int m;
-   struct tcs_group *tcs = >tcs[type];
-
-   /* Caller ensures nobody else is running so no lock */
-   if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS))
-   return;
-
-   for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++)
-   write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], m, 0);
-
-   bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
-}
-
-/**
- * rpmh_rsc_invalidate() - Invalidate sleep and wake TCSes.
- * @drv: The RSC controller.
- *
- * The caller must ensure that no other RPMH actions are happening when this
- * function is called, since otherwise the device may immediately become
- * used again even before this function exits.
- */
-void rpmh_rsc_invalidate(struct rsc_drv *drv)
-{
-   tcs_invalidate(drv, SLEEP_TCS);
-   tcs_invalidate(drv, WAKE_TCS);
-}
-
 /**
  * get_tcs_for_msg() - Get the tcs_group used to send the given message.
  * @drv: The RSC controller.
  * @msg: The message we want to send.
@@ -331,158 +290,8 @@ static struct tcs_group *get_tcs_for_msg(struct rsc_drv 
*drv,
 
return tcs;
 }
 
-/**
- * get_req_from_tcs() - Get a stashed request that was xfering on the given 
TCS.
- * @drv:The RSC controller.
- * @tcs_id: The global ID of this TCS.
- *
- * For ACTIVE_ONLY transfers we want to call back into the client when the
- * transfer finishes. To do this we need the "request" that the client
- * originally provided us. This function grabs the request that we stashed
- * when we started the transfer.
- *
- * This only makes sense for ACTIVE_ONLY transfers since those are the only
- * ones we track sending (the only ones we enable interrupts for and the only
- * ones we call back to the client for).
- *
- * Return: The stashed request.
- */
-static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv,
- int tcs_id)
-{
-   struct tcs_group *tcs;
-   int i;
-
-   for (i = 0; i < TCS_TYPE_NR; i++) {
-   tcs = >tcs[i];
-   if (tcs->mask & BIT(tcs_id))
-   return tcs->req[tcs_id - tcs->offset];
-   }
-
-   return NULL;
-}
-
-/**
- * __tcs_set_trigger() - Start xfer on a TCS or unset trigger on a borrowed TCS
- * @drv: The controller.
- * @tcs_id:  The global ID of this TCS.
- * @trigger: If true then untrigger/retrigger. If false then just untrigger.
- *
- * In the normal case we only ever call with "trigger=true" to start a
- * transfer. That will un-trigger/disable the TCS from the last transfer
- * then trigger/enable for this transfer.
- *
- * If we borrowed a wake TCS for an active-only transfer we'll also call
- * this function with "trigger=false" to just do the un-trigger/disable
- * before using the TCS for wake purposes again.
- *
- * Note that the AP is only in charge of triggering acti

[PATCH v5 08/23] soc: qcom: rpmh-rsc: adjust headers for U-Boot

2024-07-11 Thread Caleb Connolly
Remove unsupported / unused Linux headers and add those needed for
U-Boot.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-rsc.c | 35 ---
 1 file changed, 12 insertions(+), 23 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index fc8321bf208f..c09214552cfb 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -5,39 +5,28 @@
  */
 
 #define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME
 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
 
-#include 
 #include 
 #include 
 #include 
 
 #include "rpmh-internal.h"
 
-#define CREATE_TRACE_POINTS
-#include "trace-rpmh.h"
-
 
 #define RSC_DRV_ID 0
 
 #define MAJOR_VER_MASK 0xFF

-- 
2.45.2



[PATCH v5 06/23] soc: qcom: cmd-db: adjust for U-Boot API

2024-07-11 Thread Caleb Connolly
Keep the header pointer in the .data section so we don't initialize it
again after relocation, adjust cmd_db_get_header() to work with the
U-Boot API, and skip validating the header since all cmd-db users are
children of the rpmh-rsc and those children will only probe if cmd-db
initializes successfully.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index 4d3fd4db8852..b852a269ae12 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -104,9 +104,9 @@ static bool cmd_db_magic_matches(const struct cmd_db_header 
*header)
 
return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
 }
 
-static struct cmd_db_header *cmd_db_header;
+static struct cmd_db_header *cmd_db_header __section(".data") = NULL;
 
 static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
 {
u16 offset = le16_to_cpu(hdr->header_offset);
@@ -127,16 +127,12 @@ static int cmd_db_get_header(const char *id, const struct 
entry_header **eh,
 const struct rsc_hdr **rh)
 {
const struct rsc_hdr *rsc_hdr;
const struct entry_header *ent;
-   int ret, i, j;
+   int i, j;
u8 query[sizeof(ent->id)] __nonstring;
 
-   ret = cmd_db_ready();
-   if (ret)
-   return ret;
-
-   strtomem_pad(query, id, 0);
+   strncpy(query, id, sizeof(query));
 
for (i = 0; i < MAX_SLV_ID; i++) {
rsc_hdr = _db_header->header[i];
if (!rsc_hdr->slv_id)

-- 
2.45.2



[PATCH v5 05/23] soc: qcom: cmd-db: replace cmd_db_ready() with cmd_db_init()

2024-07-11 Thread Caleb Connolly
Using the driver model for cmd-db is fine, but it's unnecessary
complexity which we can just avoid in U-Boot. Instead let's just have a
function to initialize it and call said function when initializing rpmh.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 74 ++-
 include/soc/qcom/cmd-db.h |  4 +--
 2 files changed, 24 insertions(+), 54 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index b6426ac3cafc..4d3fd4db8852 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -122,24 +122,8 @@ rsc_offset(const struct rsc_hdr *hdr, const struct 
entry_header *ent)
 
return cmd_db_header->data + offset + loffset;
 }
 
-/**
- * cmd_db_ready - Indicates if command DB is available
- *
- * Return: 0 on success, errno otherwise
- */
-int cmd_db_ready(void)
-{
-   if (cmd_db_header == NULL)
-   return -EPROBE_DEFER;
-   else if (!cmd_db_magic_matches(cmd_db_header))
-   return -EINVAL;
-
-   return 0;
-}
-EXPORT_SYMBOL_GPL(cmd_db_ready);
-
 static int cmd_db_get_header(const char *id, const struct entry_header **eh,
 const struct rsc_hdr **rh)
 {
const struct rsc_hdr *rsc_hdr;
@@ -193,55 +177,41 @@ u32 cmd_db_read_addr(const char *id)
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
 EXPORT_SYMBOL_GPL(cmd_db_read_addr);
 
-static int cmd_db_dev_probe(struct platform_device *pdev)
+int cmd_db_init(void)
 {
-   struct reserved_mem *rmem;
-   int ret = 0;
+   void __iomem *base;
+   ofnode rmem, node;
 
-   rmem = of_reserved_mem_lookup(pdev->dev.of_node);
-   if (!rmem) {
-   dev_err(>dev, "failed to acquire memory region\n");
-   return -EINVAL;
+   if (cmd_db_header)
+   return 0;
+
+   rmem = ofnode_path("/reserved-memory");
+   ofnode_for_each_subnode(node, rmem) {
+   if (ofnode_device_is_compatible(node, "qcom,cmd-db"))
+   goto found;
}
 
-   cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
-   if (!cmd_db_header) {
-   ret = -ENOMEM;
-   cmd_db_header = NULL;
-   return ret;
+   log_err("%s: Failed to find cmd-db node\n", __func__);
+   return -ENOENT;
+found:
+   debug("%s(%s)\n", __func__, ofnode_get_name(node));
+
+   base = (void __iomem *)ofnode_get_addr(node);
+   if ((fdt_addr_t)base == FDT_ADDR_T_NONE) {
+   log_err("%s: Failed to read base address\n", __func__);
+   return -ENOENT;
}
 
+   cmd_db_header = base;
if (!cmd_db_magic_matches(cmd_db_header)) {
-   dev_err(>dev, "Invalid Command DB Magic\n");
+   log_err("%s: Invalid Command DB Magic\n", __func__);
return -EINVAL;
}
 
-   device_set_pm_not_required(>dev);
-
return 0;
 }
-
-static const struct of_device_id cmd_db_match_table[] = {
-   { .compatible = "qcom,cmd-db" },
-   { }
-};
-MODULE_DEVICE_TABLE(of, cmd_db_match_table);
-
-static struct platform_driver cmd_db_dev_driver = {
-   .probe  = cmd_db_dev_probe,
-   .driver = {
-  .name = "cmd-db",
-  .of_match_table = cmd_db_match_table,
-  .suppress_bind_attrs = true,
-   },
-};
-
-static int __init cmd_db_device_init(void)
-{
-   return platform_driver_register(_db_dev_driver);
-}
-core_initcall(cmd_db_device_init);
+EXPORT_SYMBOL(cmd_db_init);
 
 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h
index 753c7923f8e5..535164cc7fb0 100644
--- a/include/soc/qcom/cmd-db.h
+++ b/include/soc/qcom/cmd-db.h
@@ -21,13 +21,13 @@ enum cmd_db_hw_type {
 
 #if IS_ENABLED(CONFIG_QCOM_COMMAND_DB)
 u32 cmd_db_read_addr(const char *resource_id);
 
-int cmd_db_ready(void);
+int cmd_db_init(void);
 #else
 static inline u32 cmd_db_read_addr(const char *resource_id)
 { return 0; }
 
-static inline int cmd_db_ready(void)
+static inline int cmd_db_init(void)
 { return -ENODEV; }
 #endif /* CONFIG_QCOM_COMMAND_DB */
 #endif /* __QCOM_COMMAND_DB_H__ */

-- 
2.45.2



[PATCH v5 02/23] soc: qcom: import rpmh and cmd-db drivers from Linux

2024-07-11 Thread Caleb Connolly
Import RPMh and cmd-db framework from Linux 6.10-rc6.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c|  393 +
 drivers/soc/qcom/rpmh-internal.h |  148 +
 drivers/soc/qcom/rpmh-rsc.c  | 1162 ++
 drivers/soc/qcom/rpmh.c  |  502 
 include/soc/qcom/cmd-db.h|   48 ++
 include/soc/qcom/rpmh.h  |   47 ++
 include/soc/qcom/tcs.h   |   81 +++
 7 files changed, 2381 insertions(+)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
new file mode 100644
index ..d84572662017
--- /dev/null
+++ b/drivers/soc/qcom/cmd-db.c
@@ -0,0 +1,393 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define NUM_PRIORITY   2
+#define MAX_SLV_ID 8
+#define SLAVE_ID_MASK  0x7
+#define SLAVE_ID_SHIFT 16
+#define SLAVE_ID(addr) FIELD_GET(GENMASK(19, 16), addr)
+#define VRM_ADDR(addr) FIELD_GET(GENMASK(19, 4), addr)
+
+/**
+ * struct entry_header: header for each entry in cmddb
+ *
+ * @id: resource's identifier
+ * @priority: unused
+ * @addr: the address of the resource
+ * @len: length of the data
+ * @offset: offset from :@data_offset, start of the data
+ */
+struct entry_header {
+   u8 id[8];
+   __le32 priority[NUM_PRIORITY];
+   __le32 addr;
+   __le16 len;
+   __le16 offset;
+};
+
+/**
+ * struct rsc_hdr: resource header information
+ *
+ * @slv_id: id for the resource
+ * @header_offset: entry's header at offset from the end of the cmd_db_header
+ * @data_offset: entry's data at offset from the end of the cmd_db_header
+ * @cnt: number of entries for HW type
+ * @version: MSB is major, LSB is minor
+ * @reserved: reserved for future use.
+ */
+struct rsc_hdr {
+   __le16 slv_id;
+   __le16 header_offset;
+   __le16 data_offset;
+   __le16 cnt;
+   __le16 version;
+   __le16 reserved[3];
+};
+
+/**
+ * struct cmd_db_header: The DB header information
+ *
+ * @version: The cmd db version
+ * @magic: constant expected in the database
+ * @header: array of resources
+ * @checksum: checksum for the header. Unused.
+ * @reserved: reserved memory
+ * @data: driver specific data
+ */
+struct cmd_db_header {
+   __le32 version;
+   u8 magic[4];
+   struct rsc_hdr header[MAX_SLV_ID];
+   __le32 checksum;
+   __le32 reserved;
+   u8 data[];
+};
+
+/**
+ * DOC: Description of the Command DB database.
+ *
+ * At the start of the command DB memory is the cmd_db_header structure.
+ * The cmd_db_header holds the version, checksum, magic key as well as an
+ * array for header for each slave (depicted by the rsc_header). Each h/w
+ * based accelerator is a 'slave' (shared resource) and has slave id indicating
+ * the type of accelerator. The rsc_header is the header for such individual
+ * slaves of a given type. The entries for each of these slaves begin at the
+ * rsc_hdr.header_offset. In addition each slave could have auxiliary data
+ * that may be needed by the driver. The data for the slave starts at the
+ * entry_header.offset to the location pointed to by the rsc_hdr.data_offset.
+ *
+ * Drivers have a stringified key to a slave/resource. They can query the slave
+ * information and get the slave id and the auxiliary data and the length of 
the
+ * data. Using this information, they can format the request to be sent to the
+ * h/w accelerator and request a resource state.
+ */
+
+static const u8 CMD_DB_MAGIC[] = { 0xdb, 0x30, 0x03, 0x0c };
+
+static bool cmd_db_magic_matches(const struct cmd_db_header *header)
+{
+   const u8 *magic = header->magic;
+
+   return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
+}
+
+static struct cmd_db_header *cmd_db_header;
+
+static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
+{
+   u16 offset = le16_to_cpu(hdr->header_offset);
+
+   return cmd_db_header->data + offset;
+}
+
+static inline void *
+rsc_offset(const struct rsc_hdr *hdr, const struct entry_header *ent)
+{
+   u16 offset = le16_to_cpu(hdr->data_offset);
+   u16 loffset = le16_to_cpu(ent->offset);
+
+   return cmd_db_header->data + offset + loffset;
+}
+
+/**
+ * cmd_db_ready - Indicates if command DB is available
+ *
+ * Return: 0 on success, errno otherwise
+ */
+int cmd_db_ready(void)
+{
+   if (cmd_db_header == NULL)
+   return -EPROBE_DEFER;
+   else if (!cmd_db_magic_matches(cmd_db_header))
+   return -EINVAL;
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(cmd_db_ready);
+
+static int cmd_db_get_header(const char *id, const struct

[PATCH v5 04/23] soc: qcom: cmd-db: drop unused functions

2024-07-11 Thread Caleb Connolly
Due to our simpler rpmh-rsc driver and lack of debugfs, we don't need
quite a few cmd-db functions, just drop them.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 144 --
 include/soc/qcom/cmd-db.h |  15 -
 2 files changed, 159 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index 685b6d530136..b6426ac3cafc 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -193,150 +193,8 @@ u32 cmd_db_read_addr(const char *id)
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
 EXPORT_SYMBOL_GPL(cmd_db_read_addr);
 
-/**
- * cmd_db_read_aux_data() - Query command db for aux data.
- *
- *  @id: Resource to retrieve AUX Data on
- *  @len: size of data buffer returned
- *
- *  Return: pointer to data on success, error pointer otherwise
- */
-const void *cmd_db_read_aux_data(const char *id, size_t *len)
-{
-   int ret;
-   const struct entry_header *ent;
-   const struct rsc_hdr *rsc_hdr;
-
-   ret = cmd_db_get_header(id, , _hdr);
-   if (ret)
-   return ERR_PTR(ret);
-
-   if (len)
-   *len = le16_to_cpu(ent->len);
-
-   return rsc_offset(rsc_hdr, ent);
-}
-EXPORT_SYMBOL_GPL(cmd_db_read_aux_data);
-
-/**
- * cmd_db_match_resource_addr() - Compare if both Resource addresses are same
- *
- * @addr1: Resource address to compare
- * @addr2: Resource address to compare
- *
- * Return: true if two addresses refer to the same resource, false otherwise
- */
-bool cmd_db_match_resource_addr(u32 addr1, u32 addr2)
-{
-   /*
-* Each RPMh VRM accelerator resource has 3 or 4 contiguous 4-byte
-* aligned addresses associated with it. Ignore the offset to check
-* for VRM requests.
-*/
-   if (addr1 == addr2)
-   return true;
-   else if (SLAVE_ID(addr1) == CMD_DB_HW_VRM && VRM_ADDR(addr1) == 
VRM_ADDR(addr2))
-   return true;
-
-   return false;
-}
-EXPORT_SYMBOL_GPL(cmd_db_match_resource_addr);
-
-/**
- * cmd_db_read_slave_id - Get the slave ID for a given resource address
- *
- * @id: Resource id to query the DB for version
- *
- * Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error
- */
-enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
-{
-   int ret;
-   const struct entry_header *ent;
-   u32 addr;
-
-   ret = cmd_db_get_header(id, , NULL);
-   if (ret < 0)
-   return CMD_DB_HW_INVALID;
-
-   addr = le32_to_cpu(ent->addr);
-   return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
-}
-EXPORT_SYMBOL_GPL(cmd_db_read_slave_id);
-
-#ifdef CONFIG_DEBUG_FS
-static int cmd_db_debugfs_dump(struct seq_file *seq, void *p)
-{
-   int i, j;
-   const struct rsc_hdr *rsc;
-   const struct entry_header *ent;
-   const char *name;
-   u16 len, version;
-   u8 major, minor;
-
-   seq_puts(seq, "Command DB DUMP\n");
-
-   for (i = 0; i < MAX_SLV_ID; i++) {
-   rsc = _db_header->header[i];
-   if (!rsc->slv_id)
-   break;
-
-   switch (le16_to_cpu(rsc->slv_id)) {
-   case CMD_DB_HW_ARC:
-   name = "ARC";
-   break;
-   case CMD_DB_HW_VRM:
-   name = "VRM";
-   break;
-   case CMD_DB_HW_BCM:
-   name = "BCM";
-   break;
-   default:
-   name = "Unknown";
-   break;
-   }
-
-   version = le16_to_cpu(rsc->version);
-   major = version >> 8;
-   minor = version;
-
-   seq_printf(seq, "Slave %s (v%u.%u)\n", name, major, minor);
-   seq_puts(seq, "-\n");
-
-   ent = rsc_to_entry_header(rsc);
-   for (j = 0; j < le16_to_cpu(rsc->cnt); j++, ent++) {
-   seq_printf(seq, "0x%05x: %*pEp", le32_to_cpu(ent->addr),
-  (int)strnlen(ent->id, sizeof(ent->id)), 
ent->id);
-
-   len = le16_to_cpu(ent->len);
-   if (len) {
-   seq_printf(seq, " [%*ph]",
-  len, rsc_offset(rsc, ent));
-   }
-   seq_putc(seq, '\n');
-   }
-   }
-
-   return 0;
-}
-
-static int open_cmd_db_debugfs(struct inode *inode, struct file *file)
-{
-   return single_open(file, cmd_db_debugfs_dump, inode->i_private);
-}
-#endif
-
-static const struct file_operations cmd_db_debugfs_ops = {
-#ifdef CONFIG_DEBUG_FS
-   .open = open_cmd_db_debugfs,
-#endif
-   .read = seq_rea

[PATCH v5 03/23] soc: qcom: cmd-db: adjust headers for U-Boot

2024-07-11 Thread Caleb Connolly
Replace unused/unsupported Linux headers with appropriate U-Boot
alternatives.

Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index d84572662017..685b6d530136 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -3,18 +3,16 @@
  * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
  * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
-#include 
-#include 
+#define pr_fmt(fmt) "cmd-db: " fmt
+
+#include 
+#include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
 #include 
+#include 
+#include 
 
 #include 
 
 #define NUM_PRIORITY   2

-- 
2.45.2



[PATCH v5 01/23] linux/bitmap.h: add bitmap_empty helper

2024-07-11 Thread Caleb Connolly
Import this function from Linux as of 6.10-rc6

Reviewed-by: Tom Rini 
Acked-by: Sumit Garg 
Signed-off-by: Caleb Connolly 
---
 include/linux/bitmap.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f14..40ca2212cb40 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -195,8 +195,16 @@ static inline void bitmap_fill(unsigned long *dst, 
unsigned int nbits)
memset(dst, 0xff, len);
}
 }
 
+static inline bool bitmap_empty(const unsigned long *src, unsigned int nbits)
+{
+   if (small_const_nbits(nbits))
+   return !(*src & BITMAP_LAST_WORD_MASK(nbits));
+
+   return find_first_bit(src, nbits) == nbits;
+}
+
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
 const unsigned long *src2, unsigned int nbits)
 {
if (small_const_nbits(nbits))

-- 
2.45.2



[PATCH v5 00/23] qcom: rpmh core and regulator support

2024-07-11 Thread Caleb Connolly
This series introduces support for the RPMh (Resource Power Manager
(hardened)) co-processor and associated regulator driver found on most
modern Qualcomm platforms (since ~2017).

Even though most regulators are controlled via SPMI, the specific
regions on the PMICs for controlling the regulators are restricted and
can't be accessed by the Applications Processor (AP/HLOS). Instead,
these resources are proxied via the RPMh where they can be voted on by
multiple subsystems (Linux, the modem, and the other DSPs). This is done
for security (to protect clocks, power domains, and regulators that are
specifically relevant for the trustzone) as well as to simplify the
management of shared peripherals and to allow for handover of
peripherals like the USB controller.

For U-Boot, our main concern is the regulators. Since all regulators on
the system are controlled via the RPMh, it is necessary to support it to
enable USB VBUS on some platforms, and may be needed for other
peripherals in the future.

Communicating with the RPMh additional requires accessing the cmd-db
shared memory region, this contains key/value maps to determine the
address of specific resources on the RPMh.

Introduce support for the cmd-db, the RPMh framework, and some of the
regulators that are necessary to enable USB VBUS on the RB5 development
board.

These drivers are taken from Linux, then modified and simplified for
U-Boot. The original Linux drivers contain heavy optimisations related
to multithreading and asynchronous probing, as well as support for idle
and suspend states which we don't need to deal with here. This unused
code is removed before finally adjusting the drivers to properly build
for U-Boot and use its device model.

The U-Boot version of the driver supports a single ACTIVE_ONLY TCS and
waits for it to be cleared after use. We don't support programming
low power states.

---
Changes in v5:
- Add Kconfig / Makefiles after introducing drivers to avoid breaking
  compilation when bisecting (Thanks Neil).
- Link to v4: 
https://lore.kernel.org/r/20240709-b4-qcom-rpmh-v4-0-c06d0a266...@linaro.org

Changes in v4:
- Denote original Linux version in bitmap.h patch
- Rebased on Linux 6.10-rc6 and re-apply U-Boot changes preserving git
  history. Allowing for future changes to the Linux drivers to be ported
  over more easily.
- Add missing check to wait for the TCS to be cleared after use (seems
  we were just racing the RPMh before, oops!).
- Fix missing n_modes in pmic5_pldo regulator.
- Link to v3: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v3-0-846cc6c5b...@linaro.org

Changes in v3:
- Don't call dm_scan_fdt_dev(), since DM core will scan.
- Link to v2: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v2-0-8bc765606...@linaro.org

Changes in v2:
- Implement Neil's suggestions and fixes for SM8[56]50
- Slightly refactor cmd_db_init() for better abstraction.
- Improve logging (printf -> log_err/dev_err)
- Add missing error check in rpmh_regulators_bind()
- Link to v1: 
https://lore.kernel.org/r/20240617-b4-qcom-rpmh-v1-0-bd2336923...@linaro.org

---
Caleb Connolly (23):
  linux/bitmap.h: add bitmap_empty helper
  soc: qcom: import rpmh and cmd-db drivers from Linux
  soc: qcom: cmd-db: adjust headers for U-Boot
  soc: qcom: cmd-db: drop unused functions
  soc: qcom: cmd-db: replace cmd_db_ready() with cmd_db_init()
  soc: qcom: cmd-db: adjust for U-Boot API
  soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS 
support
  soc: qcom: rpmh-rsc: adjust headers for U-Boot
  soc: qcom: rpmh-rsc: adjust probe for U-Boot
  soc: qcom: rpmh-rsc: remaining U-Boot API changes
  soc: qcom: rpmh: adjust headers for U-Boot
  soc: qcom: rpmh: drop unused functions
  soc: qcom: rpmh: U-Boot API changes
  soc: qcom: add build infrastructure
  power: regulator: import qcom-rpmh-regulator from Linux
  power: regulator: qcom-rpmh-regulator: adjust headers for U-Boot
  power: regulator: qcom-rpmh-regulator: port over lineage_range helpers
  power: regulator: qcom-rpmh-regulator: adjust structs for U-Boot
  power: regulator: qcom-rpmh-regulator: remove unused regulators
  power: regulator: qcom-rpmh-regulator: port ops to U-Boot
  power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot
  power: regulator: qcom-rpmh-regulator: add build infra
  qcom_defconfig: enable rpmh regulators

 configs/qcom_defconfig|   5 +
 drivers/power/regulator/Kconfig   |   8 +
 drivers/power/regulator/Makefile  |   1 +
 drivers/power/regulator/qcom-rpmh-regulator.c | 544 ++
 drivers/soc/Kconfig   |   1 +
 drivers/soc/Makefile  |   1 +
 drivers/soc/qcom/Kconfig  |  27 ++
 drivers/soc/qcom/Makefile |   4 +
 drivers/soc/qcom/cmd-db.c | 213 ++
 drivers/soc/qcom/r

Re: [PATCH v4 00/21] qcom: rpmh core and regulator support

2024-07-10 Thread Caleb Connolly




On 10/07/2024 13:33, Sumit Garg wrote:

Hi Caleb,

On Tue, 9 Jul 2024 at 15:04, Caleb Connolly  wrote:


This series introduces support for the RPMh (Resource Power Manager
(hardened)) co-processor and associated regulator driver found on most
modern Qualcomm platforms (since ~2017).

Even though most regulators are controlled via SPMI, the specific
regions on the PMICs for controlling the regulators are restricted and
can't be accessed by the Applications Processor (AP/HLOS). Instead,
these resources are proxied via the RPMh where they can be voted on by
multiple subsystems (Linux, the modem, and the other DSPs). This is done
for security (to protect clocks, power domains, and regulators that are
specifically relevant for the trustzone) as well as to simplify the
management of shared peripherals and to allow for handover of
peripherals like the USB controller.

For U-Boot, our main concern is the regulators. Since all regulators on
the system are controlled via the RPMh, it is necessary to support it to
enable USB VBUS on some platforms, and may be needed for other
peripherals in the future.

Communicating with the RPMh additional requires accessing the cmd-db
shared memory region, this contains key/value maps to determine the
address of specific resources on the RPMh.

Introduce support for the cmd-db, the RPMh framework, and some of the
regulators that are necessary to enable USB VBUS on the RB5 development
board.

These drivers are taken from Linux, then modified and simplified for
U-Boot. The original Linux drivers contain heavy optimisations related
to multithreading and asynchronous probing, as well as support for idle
and suspend states which we don't need to deal with here. This unused
code is removed before finally adjusting the drivers to properly build
for U-Boot and use its device model.

The U-Boot version of the driver supports a single ACTIVE_ONLY TCS and
waits for it to be cleared after use. We don't support programming
low power states.

---
Changes in v4:
- Denote original Linux version in bitmap.h patch
- Rebased on Linux 6.10-rc6 and re-apply U-Boot changes preserving git
   history. Allowing for future changes to the Linux drivers to be ported
   over more easily.
- Add missing check to wait for the TCS to be cleared after use (seems
   we were just racing the RPMh before, oops!).
- Fix missing n_modes in pmic5_pldo regulator.
- Link to v3: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v3-0-846cc6c5b...@linaro.org


Thanks for doing this, this looks much better from a maintainability
perspective. Although I am seeing a lot of patches saying adjustments
and build fixes, I think you should have taken care of commits
bisect-ability such that individual commits don't cause any build
errors.


I'll send a v5 which holds off on adding the Kconfig/Makefile parts 
until after the code is adjusted, this will prevent breaking bisection 
and still make it easy for us to cherry-pick commits from Linux with 
some git magic.


FWIW, for the series:

Acked-by: Sumit Garg 


Thanks,


-Sumit



Changes in v3:
- Don't call dm_scan_fdt_dev(), since DM core will scan.
- Link to v2: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v2-0-8bc765606...@linaro.org

Changes in v2:
- Implement Neil's suggestions and fixes for SM8[56]50
- Slightly refactor cmd_db_init() for better abstraction.
- Improve logging (printf -> log_err/dev_err)
- Add missing error check in rpmh_regulators_bind()
- Link to v1: 
https://lore.kernel.org/r/20240617-b4-qcom-rpmh-v1-0-bd2336923...@linaro.org

---
Caleb Connolly (21):
   linux/bitmap.h: add bitmap_empty helper
   soc: qcom: import rpmh and cmd-db drivers from Linux
   soc: qcom: cmd-db: adjust headers for U-Boot
   soc: qcom: cmd-db: drop unused functions
   soc: qcom: cmd-db: replace cmd_db_ready() with cmd_db_init()
   soc: qcom: cmd-db: adjust for U-Boot API
   soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS 
support
   soc: qcom: rpmh-rsc: adjust headers for U-Boot
   soc: qcom: rpmh-rsc: adjust probe for U-Boot
   soc: qcom: rpmh-rsc: remaining U-Boot API changes
   soc: qcom: rpmh: adjust headers for U-Boot
   soc: qcom: rpmh: drop unused functions
   soc: qcom: rpmh: U-Boot API changes
   power: regulator: import qcom-rpmh-regulator from Linux
   power: regulator: adjust headers for U-Boot
   power: regulator: qcom-rpmh-regulator: port over lineage_range helpers
   power: regulator: adjust structs for U-Boot
   power: regulator: qcom-rpmh-regulator: remove unused regulators
   power: regulator: qcom-rpmh-regulator: port ops to U-Boot
   power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot
   qcom_defconfig: enable rpmh regulators

  configs/qcom_defconfig|   5 +
  drivers/power/regulator/Kconfig   |   8 +
  drivers/power/regulator/Makefile  |   1 +
  drivers/power/regulator/qcom-rpmh-regulator.c | 

[PATCH RFC 3/3] arm64: unwind stack on exception

2024-07-10 Thread Caleb Connolly
We already build arm64 images with frame pointers. Let's finally make
use of them in tandem with the new symbol lookup support by unwinding
the stack when an exception occurs, producing a backtrace similar to
those emitted by Linux.

In addition, introduce a dedicated unwind_stack() function which can be
called from anywhere to print a backtrace.

Signed-off-by: Caleb Connolly 
---
 arch/arm/include/asm/ptrace.h |  4 +++
 arch/arm/lib/interrupts_64.c  | 76 +++
 lib/Kconfig   |  6 ++--
 3 files changed, 84 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index a836f6cc60db..f42cfb33e918 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -22,8 +22,12 @@
 
 #ifdef __KERNEL__
 extern void show_regs(struct pt_regs *);
 
+#if CONFIG_IS_ENABLED(SYMBOL_LOOKUP)
+void unwind_stack(void);
+#endif
+
 #define predicate(x)   (x & 0xf000)
 #define PREDICATE_ALWAYS   0xe000
 
 #endif
diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c
index b3024ba514ec..24edeb0de51e 100644
--- a/arch/arm/lib/interrupts_64.c
+++ b/arch/arm/lib/interrupts_64.c
@@ -3,15 +3,17 @@
  * (C) Copyright 2013
  * David Feng 
  */
 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 
 DECLARE_GLOBAL_DATA_PTR;
 
 int interrupt_init(void)
@@ -80,8 +82,77 @@ static void dump_instr(struct pt_regs *regs)
printf(i == 0 ? "(%08x) " : "%08x ", addr[i]);
printf("\n");
 }
 
+#if IS_ENABLED(CONFIG_SYMBOL_LOOKUP)
+
+static void print_sym(unsigned long symaddr, const char *symname, unsigned 
long offset)
+{
+   if (symaddr > (unsigned long)__bss_end)
+   printf("\t<%#016lx> ???\n", symaddr);
+   else
+   printf("\t<%#016lx> %s+%#lx\n", symaddr, symname, offset);
+}
+
+/* Stack frames automatically generated by compiler emitted code */
+struct stack_frame {
+   struct stack_frame *prev_ptr; /* Alays a bigger address on ARM64 */
+   unsigned long lr;
+   char data[];
+};
+
+static void __unwind_stack(unsigned long lr, unsigned long x29)
+{
+   char symname[KSYM_NAME_LEN+1] = { 0 };
+   unsigned long addr, offset;
+   struct stack_frame *fp, *last_fp;
+
+   /*
+* Either the place where unwind_stack() was called, or the
+* instruction that caused an exception
+*/
+   symbols_lookup(lr, , , symname);
+   print_sym(addr, symname, offset);
+
+   fp = (struct stack_frame *)x29;
+   while (fp && fp->prev_ptr > fp) {
+   symbols_lookup(fp->lr, , , symname);
+   /*
+* _start is used over gd->relocaddr because it will be correct
+* if U-Boot was built as relocatable and loaded at an arbitrary
+* address (both pre and post-relocation).
+*/
+   print_sym(addr + (unsigned long)_start, symname, offset);
+   last_fp = fp;
+   fp = (struct stack_frame *)(u64)fp->prev_ptr;
+   }
+}
+
+/**
+ * unwind_stack() - Unwind the callstack and print a backtrace.
+ *
+ * This function can be called for debugging purposes to walk backwards through
+ * stack frames, printing the function name and offset of the branch 
instruction.
+ *
+ * It reads out the link register (x30) which contains the return address of 
the
+ * caller, and x29 which contains the frame pointer of the caller.
+ */
+void unwind_stack(void)
+{
+   unsigned long x29, x30;
+
+   asm("mov %0, x29" : "=r" (x29));
+   asm("mov %0, x30" : "=r" (x30));
+
+   __unwind_stack(x30, x29);
+}
+
+#else
+
+#define __unwind_stack(lr, x29) do {} while (0)
+
+#endif
+
 void show_regs(struct pt_regs *regs)
 {
int i;
 
@@ -95,8 +166,13 @@ void show_regs(struct pt_regs *regs)
printf("x%-2d: %016lx x%-2d: %016lx\n",
   i, regs->regs[i], i+1, regs->regs[i+1]);
printf("\n");
dump_instr(regs);
+
+   if (IS_ENABLED(CONFIG_SYMBOL_LOOKUP)) {
+   printf("\nBacktrace:\n");
+   __unwind_stack(regs->elr, regs->regs[29]);
+   }
 }
 
 /*
  * Try to "emulate" a semihosting call in the event that we don't have a
diff --git a/lib/Kconfig b/lib/Kconfig
index 06a78f83b7d6..092b780aeeb8 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -979,11 +979,13 @@ config VPL_OF_LIBFDT_ASSUME_MASK
  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
 
 config SYMBOL_LOOKUP
bool "Enable symbol lookup"
+   default n
help
- This enables support for looking up symbol names from addresses. The
- primary usecase for this is improved debugging support

[PATCH RFC 2/3] add support for symbol lookups

2024-07-10 Thread Caleb Connolly
This is mostly a port of the Xen hypervisor implementation. The U-Boot
binary is built as normal, then its symbol table is fed into
tools/symbols to generate an optimised lookup table. U-Boot is rebuilt
with the symbol table and handling code in lib/symbols.c.

Based on code from Xen at
  c20850540ad6("x86/altcall: always use a temporary parameter stashing 
variable")

Signed-off-by: Caleb Connolly 
---
 Makefile  |  15 +-
 include/symbols.h |  19 ++
 lib/Kconfig   |   6 +
 lib/Makefile  |   1 +
 lib/symbols.c | 126 +++
 tools/Makefile|   3 +
 tools/symbols.c   | 646 ++
 7 files changed, 815 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index fcb9565d2fff..ae899fe97724 100644
--- a/Makefile
+++ b/Makefile
@@ -1781,16 +1781,29 @@ quiet_cmd_u-boot__ ?= LD  $@
   cmd_u-boot__ ?= $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_u-boot) -o $@  
\
-T u-boot.lds $(u-boot-init)
\
--whole-archive 
\
$(u-boot-main)  
\
+   $(if $(shell [ "$@" = "u-boot" ] && echo 
"true"),lib/symbols.o u-boot.sym.o,)   \
--no-whole-archive  
\
$(PLATFORM_LIBS) -Map u-boot.map;   
\
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
 endif
 
-u-boot:$(u-boot-init) $(u-boot-main) $(u-boot-keep-syms-lto) 
u-boot.lds FORCE
+u-boot.nosyms: $(u-boot-init) $(u-boot-main) $(u-boot-keep-syms-lto) 
u-boot.lds FORCE
+$(call if_changed,u-boot__)
 
+ifeq ($(CONFIG_SYMBOL_LOOKUP),y)
+u-boot: u-boot.nosyms FORCE
+   @$(NM) -n -pa --format=sysv u-boot.nosyms | tools/symbols --all-symbols 
--sysv --sort > u-boot.sym.S
+   @$(CC) $(c_flags) -c $(srctree)/lib/symbols.c -o lib/symbols.o
+   @$(AS) u-boot.sym.S -o u-boot.sym.o
+   @$(call cmd,u-boot__)
+else
+u-boot: u-boot.nosyms FORCE
+   +$(call if_changed,copy)
+endif
+
+
 ifeq ($(CONFIG_RISCV),y)
@tools/prelink-riscv $@
 endif
 
diff --git a/include/symbols.h b/include/symbols.h
new file mode 100644
index ..b17f122be339
--- /dev/null
+++ b/include/symbols.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#include 
+#include 
+
+#define KSYM_NAME_LEN 127
+
+#if IS_ENABLED(CONFIG_SYMBOL_LOOKUP)
+const char * __attribute__((weak)) symbols_lookup(unsigned long addr, unsigned 
long *symaddr, unsigned long *offset,
+  char *namebuf);
+#else
+static inline const char *symbols_lookup(unsigned long addr, unsigned long 
*symaddr, unsigned long *offset,
+  char *namebuf)
+{
+   strcpy(namebuf, "???");
+   namebuf[3] = '\0';
+   return namebuf;
+}
+#endif
diff --git a/lib/Kconfig b/lib/Kconfig
index b3baa4b85b07..06a78f83b7d6 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -977,8 +977,14 @@ config VPL_OF_LIBFDT_ASSUME_MASK
  are made, and libfdt is able to deal with malicious data. A value of
  0xff means all assumptions are made and any invalid data may cause
  unsafe execution. See FDT_ASSUME_PERFECT, etc. in libfdt_internal.h
 
+config SYMBOL_LOOKUP
+   bool "Enable symbol lookup"
+   help
+ This enables support for looking up symbol names from addresses. The
+ primary usecase for this is improved debugging support.
+
 menu "System tables"
depends on (!EFI && !SYS_COREBOOT) || (ARM && EFI_LOADER)
 
 config BLOBLIST_TABLES
diff --git a/lib/Makefile b/lib/Makefile
index e389ad014f89..a4ccda76f438 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -121,8 +121,9 @@ obj-y += linux_string.o
 obj-$(CONFIG_LMB) += lmb.o
 obj-y += membuff.o
 obj-$(CONFIG_REGEX) += slre.o
 obj-y += string.o
+#obj-y += symbols.o
 obj-y += tables_csum.o
 obj-y += time.o
 obj-y += hexdump.o
 obj-$(CONFIG_GETOPT) += getopt.o
diff --git a/lib/symbols.c b/lib/symbols.c
new file mode 100644
index ..e881d5603425
--- /dev/null
+++ b/lib/symbols.c
@@ -0,0 +1,126 @@
+/*
+ * symbols.c: in-kernel printing of symbolic oopses and stack traces.
+ * Ported from Xen hypervisor
+ *
+ * Copyright 2002 Rusty Russell  IBM Corporation
+ *
+ * ChangeLog:
+ *
+ * (25/Aug/2004) Paulo Marques 
+ *  Changed the compression method from stem compression to "table lookup"
+ *  compression (see tools/symbols.c for a more complete description)
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+extern const uint64_t symbols_offsets[];
+extern const unsigned int symbols_num_syms;
+extern const u8 symbols_names[];
+extern const u8 symbols_token_table[];
+extern const u16 symbols_token_ind

[PATCH RFC 1/3] drop unused kallsyms support

2024-07-10 Thread Caleb Connolly
There was some very old code floating around for decoding symbols, it's
incomplete and is never built. Remove it so we can add a new
implementation.

Signed-off-by: Caleb Connolly 
---
 Makefile| 11 ---
 common/Makefile |  1 -
 common/kallsyms.c   | 43 ---
 common/system_map.c |  8 
 4 files changed, 63 deletions(-)

diff --git a/Makefile b/Makefile
index f5b2512f3690..fcb9565d2fff 100644
--- a/Makefile
+++ b/Makefile
@@ -1786,21 +1786,10 @@ quiet_cmd_u-boot__ ?= LD  $@
$(PLATFORM_LIBS) -Map u-boot.map;   
\
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
 endif
 
-quiet_cmd_smap = GEN common/system_map.o
-cmd_smap = \
-   smap=`$(call SYSTEM_MAP,u-boot) | \
-   awk '$$2 ~ /[tTwW]/ {printf $$1 $$3 "000"}'` ; \
-   $(CC) $(c_flags) -DSYSTEM_MAP="\"$${smap}\"" \
-   -c $(srctree)/common/system_map.c -o common/system_map.o
-
 u-boot:$(u-boot-init) $(u-boot-main) $(u-boot-keep-syms-lto) 
u-boot.lds FORCE
+$(call if_changed,u-boot__)
-ifeq ($(CONFIG_KALLSYMS),y)
-   $(call cmd,smap)
-   $(call cmd,u-boot__) common/system_map.o
-endif
 
 ifeq ($(CONFIG_RISCV),y)
@tools/prelink-riscv $@
 endif
diff --git a/common/Makefile b/common/Makefile
index e98354734206..bca02e4c362f 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -34,9 +34,8 @@ obj-$(CONFIG_USB_ONBOARD_HUB) += usb_onboard_hub.o
 obj-$(CONFIG_CONSOLE_MUX) += iomux.o
 obj-$(CONFIG_MTD_NOR_FLASH) += flash.o
 obj-$(CONFIG_CMD_KGDB) += kgdb.o kgdb_stubs.o
 obj-$(CONFIG_I2C_EDID) += edid.o
-obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-y += splash.o
 obj-$(CONFIG_SPLASH_SOURCE) += splash_source.o
 obj-$(CONFIG_MENU) += menu.o
 obj-$(CONFIG_UPDATE_COMMON) += update.o
diff --git a/common/kallsyms.c b/common/kallsyms.c
deleted file mode 100644
index 49b3897078ae..
--- a/common/kallsyms.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Helper functions for working with the builtin symbol table
- *
- * Copyright (c) 2008-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or later.
- */
-
-
-/* We need the weak marking as this symbol is provided specially */
-extern const char system_map[] __attribute__((weak));
-
-/* Given an address, return a pointer to the symbol name and store
- * the base address in caddr.  So if the symbol map had an entry:
- * 03fb9b7c_spi_cs_deactivate
- * Then the following call:
- * unsigned long base;
- * const char *sym = symbol_lookup(0x03fb9b80, );
- * Would end up setting the variables like so:
- * base = 0x03fb9b7c;
- * sym = "_spi_cs_deactivate";
- */
-const char *symbol_lookup(unsigned long addr, unsigned long *caddr)
-{
-   const char *sym, *csym;
-   char *esym;
-   unsigned long sym_addr;
-
-   sym = system_map;
-   csym = NULL;
-   *caddr = 0;
-
-   while (*sym) {
-   sym_addr = hextoul(sym, );
-   sym = esym;
-   if (sym_addr > addr)
-   break;
-   *caddr = sym_addr;
-   csym = sym;
-   sym += strlen(sym) + 1;
-   }
-
-   return csym;
-}
diff --git a/common/system_map.c b/common/system_map.c
deleted file mode 100644
index 8307293bf3ae..
--- a/common/system_map.c
+++ /dev/null
@@ -1,8 +0,0 @@
-/*
- * The builtin symbol table for use with kallsyms
- *
- * Copyright (c) 2008-2009 Analog Devices Inc.
- * Licensed under the GPL-2 or later.
- */
-
-const char const system_map[] = SYSTEM_MAP;

-- 
2.45.2



[PATCH RFC 0/3] ARM64: add symbol name lookup and print a backtrace on exception

2024-07-10 Thread Caleb Connolly
U-Boot already emits frame pointers on ARM64, but lacks the code to
parse them, as well as a mechanism for looking up symbol names at
runtime.

There was some (seemingly?) leftover code for symbols lookups in
common/kallsyms.c and associated parts in the makefile, however it
appears to be entirely unused and unsupported. It relied on generating
one long string of all symbol addresses and names.

The approach taken here is instead largely based on the implementation
in the Xen hypervisor, it performs basic compression using non-ASCII
bytes to tokenize repeated string segments which can later be expanded
back out at runtime.

This is then utilized in the ARM64 interrupt handling routine to dump a
backtrace in the show_regs() debug function. As well as providing a
general purpose unwind_stack() function which can be used for debugging.

== Relocation ==

Since U-Boot relocates itself at runtime, and can be built to be
position independent in the first place (effectively "relocating" itself
when it first starts too), we can't really rely on gd->reloc_off.

The approach taken here is to subtract CONFIG_TEXT_BASE from the address
of each symbol in the lookup table (while it's being generated), then
when decoding we just subtract the address of the _start label. Since
this label address is updated to make U-Boot position independent and
during relocation, it allows us to avoid re-implementing the relocation
state handling stuff in the symbol decoder.

== Size ==

By default this feature is off, and will not effect the size of U-Boot
binaries. The generated symbols object file is ~85k with the (fairly
hefty) qcom_defconfig, so there is certainly a cost to be taken into
account.

I hope that this implementation can be later extended for other
platforms. However this is currently beyond my (skill, time)
capabilities.

---
Caleb Connolly (3):
  drop unused kallsyms support
  add support for symbol lookups
  arm64: unwind stack on exception

 Makefile  |  24 +-
 arch/arm/include/asm/ptrace.h |   4 +
 arch/arm/lib/interrupts_64.c  |  76 +
 common/Makefile   |   1 -
 common/kallsyms.c |  43 ---
 common/system_map.c   |   8 -
 include/symbols.h |  19 ++
 lib/Kconfig   |   8 +
 lib/Makefile  |   1 +
 lib/symbols.c | 126 
 tools/Makefile|   3 +
 tools/symbols.c   | 646 ++
 12 files changed, 896 insertions(+), 63 deletions(-)
---
change-id: 20240710-arm64-backtrace-2926f764dbdc
base-commit: 13f9c5668411aa18ef64846d5bc86e9e6be52082

// Caleb (they/them)



[PATCH v4 10/21] soc: qcom: rpmh-rsc: remaining U-Boot API changes

2024-07-09 Thread Caleb Connolly
Minor adjustments to fix building with U-Boot and work correctly as a
synchronous driver without interrupts. RPMh is fast enough that we can
get away with just firing off requests and assuming they complete.

U-Boot behaviour changes are annotated with a "U-Boot:" comment.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-rsc.c | 78 +
 1 file changed, 29 insertions(+), 49 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index d4ef88dda184..566fa16baba9 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -134,16 +134,8 @@ enum {
  *  |  ..   |
  *  +---+
  */
 
-#define USECS_TO_CYCLES(time_usecs)\
-   xloops_to_cycles((time_usecs) * 0x10C7UL)
-
-static inline unsigned long xloops_to_cycles(u64 xloops)
-{
-   return (xloops * loops_per_jiffy * HZ) >> 32;
-}
-
 static u32 rpmh_rsc_reg_offset_ver_2_7[] = {
[RSC_DRV_TCS_OFFSET]= 672,
[RSC_DRV_CMD_OFFSET]= 20,
[DRV_SOLVER_CONFIG] = 0x04,
@@ -248,37 +240,18 @@ static void write_tcs_reg_sync(const struct rsc_drv *drv, 
int reg, int tcs_id,
  */
 static struct tcs_group *get_tcs_for_msg(struct rsc_drv *drv,
 const struct tcs_request *msg)
 {
-   int type;
-   struct tcs_group *tcs;
-
-   switch (msg->state) {
-   case RPMH_ACTIVE_ONLY_STATE:
-   type = ACTIVE_TCS;
-   break;
-   case RPMH_WAKE_ONLY_STATE:
-   type = WAKE_TCS;
-   break;
-   case RPMH_SLEEP_STATE:
-   type = SLEEP_TCS;
-   break;
-   default:
+   /*
+* U-Boot: since we're single threaded and running synchronously we can
+* just always used the first active TCS.
+*/
+   if (msg->state != RPMH_ACTIVE_ONLY_STATE) {
+   log_err("WARN: only ACTIVE_ONLY state supported\n");
return ERR_PTR(-EINVAL);
}
 
-   /*
-* If we are making an active request on a RSC that does not have a
-* dedicated TCS for active state use, then re-purpose a wake TCS to
-* send active votes. This is safe because we ensure any active-only
-* transfers have finished before we use it (maybe by running from
-* the last CPU in PM code).
-*/
-   tcs = >tcs[type];
-   if (msg->state == RPMH_ACTIVE_ONLY_STATE && !tcs->num_tcs)
-   tcs = >tcs[WAKE_TCS];
-
-   return tcs;
+   return >tcs[ACTIVE_TCS];
 }
 
 /**
  * __tcs_buffer_write() - Write to TCS hardware from a request; don't trigger.
@@ -298,11 +271,8 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
u32 cmd_enable = 0;
struct tcs_cmd *cmd;
int i, j;
 
-   /* Convert all commands to RR when the request has wait_for_compl set */
-   cmd_msgid |= msg->wait_for_compl ? CMD_MSGID_RESP_REQ : 0;
-
for (i = 0, j = cmd_id; i < msg->num_cmds; i++, j++) {
cmd = >cmds[i];
cmd_enable |= BIT(j);
msgid = cmd_msgid;
@@ -314,9 +284,11 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
 
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, 
msgid);
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, 
cmd->addr);
write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, 
cmd->data);
-   trace_rpmh_send_msg(drv, tcs_id, msg->state, j, msgid, cmd);
+   debug("tcs(m): %d [%s] cmd(n): %d msgid: %#x addr: %#x data: 
%#x complete: %d\n",
+ tcs_id, msg->state == RPMH_ACTIVE_ONLY_STATE ? "active" : 
"?", j, msgid,
+ cmd->addr, cmd->data, cmd->wait);
}
 
cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id);
write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable);
@@ -346,34 +318,28 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int 
tcs_id, int cmd_id,
  */
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
 {
struct tcs_group *tcs;
-   int tcs_id;
-
-   might_sleep();
+   int tcs_id, i;
+   u32 addr;
 
tcs = get_tcs_for_msg(drv, msg);
if (IS_ERR(tcs))
return PTR_ERR(tcs);
 
-   spin_lock_irq(>lock);
-
-   /* Wait forever for a free tcs. It better be there eventually! */
-   wait_event_lock_irq(drv->tcs_wait,
-   (tcs_id = claim_tcs_for_req(drv, tcs, msg)) >= 0,
-   drv->lock);
+   /* u-boot is single-threaded, always u

[PATCH v4 21/21] qcom_defconfig: enable rpmh regulators

2024-07-09 Thread Caleb Connolly
Enable RPMh, cmd-db, and RPMh regulators. Additionally enable
CMD_REGULATOR for debugging.

Signed-off-by: Caleb Connolly 
---
 configs/qcom_defconfig | 5 +
 1 file changed, 5 insertions(+)

diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index 60a8e38cc6bb..8a55bb9af708 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -35,8 +35,9 @@ CONFIG_CMD_UFS=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_CAT=y
 CONFIG_CMD_BMP=y
 CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_REGULATOR=y
 CONFIG_CMD_LOG=y
 CONFIG_OF_LIVE=y
 CONFIG_BUTTON_QCOM_PMIC=y
 CONFIG_CLK=y
@@ -90,11 +91,15 @@ CONFIG_PINCTRL_QCOM_SM8650=y
 CONFIG_DM_PMIC=y
 CONFIG_PMIC_QCOM=y
 CONFIG_DM_REGULATOR=y
 CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_DM_REGULATOR_QCOM_RPMH=y
 CONFIG_SCSI=y
 CONFIG_MSM_SERIAL=y
 CONFIG_MSM_GENI_SERIAL=y
+CONFIG_SOC_QCOM=y
+CONFIG_QCOM_COMMAND_DB=y
+CONFIG_QCOM_RPMH=y
 CONFIG_SPMI_MSM=y
 CONFIG_SYSINFO=y
 CONFIG_SYSINFO_SMBIOS=y
 CONFIG_USB=y

-- 
2.45.2



[PATCH v4 18/21] power: regulator: qcom-rpmh-regulator: remove unused regulators

2024-07-09 Thread Caleb Connolly
Initially just include the few regulators needed for the RB5 board.
Others can be added back as-needed.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 1281 -
 1 file changed, 1281 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 089623f3a2b9..2a8e8f9ac444 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -338,68 +338,8 @@ static unsigned int rpmh_regulator_vrm_get_mode(struct 
regulator_dev *rdev)
 
return vreg->mode;
 }
 
-/**
- * rpmh_regulator_vrm_get_optimum_mode() - get the mode based on the  load
- * @rdev:  Regulator device pointer for the rpmh-regulator
- * @input_uV:  Input voltage
- * @output_uV: Output voltage
- * @load_uA:   Aggregated load current in microamps
- *
- * This function is used in the regulator_ops for VRM type RPMh regulator
- * devices.
- *
- * Return: 0 on success, errno on failure
- */
-static unsigned int rpmh_regulator_vrm_get_optimum_mode(
-   struct regulator_dev *rdev, int input_uV, int output_uV, int load_uA)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-
-   if (load_uA >= vreg->hw_data->hpm_min_load_uA)
-   return REGULATOR_MODE_NORMAL;
-   else
-   return REGULATOR_MODE_IDLE;
-}
-
-static int rpmh_regulator_vrm_set_bypass(struct regulator_dev *rdev,
-   bool enable)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-   int ret;
-
-   if (vreg->bypassed == enable)
-   return 0;
-
-   ret = rpmh_regulator_vrm_set_mode_bypass(vreg, vreg->mode, enable);
-   if (!ret)
-   vreg->bypassed = enable;
-
-   return ret;
-}
-
-static int rpmh_regulator_vrm_get_bypass(struct regulator_dev *rdev,
-   bool *enable)
-{
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
-
-   *enable = vreg->bypassed;
-
-   return 0;
-}
-
-static const struct regulator_ops rpmh_regulator_vrm_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-   .set_voltage_sel= rpmh_regulator_vrm_set_voltage_sel,
-   .get_voltage_sel= rpmh_regulator_vrm_get_voltage_sel,
-   .list_voltage   = regulator_list_voltage_linear_range,
-   .set_mode   = rpmh_regulator_vrm_set_mode,
-   .get_mode   = rpmh_regulator_vrm_get_mode,
-};
-
 static const struct regulator_ops rpmh_regulator_vrm_drms_ops = {
.enable = rpmh_regulator_enable,
.disable= rpmh_regulator_disable,
.is_enabled = rpmh_regulator_is_enabled,
@@ -410,331 +350,8 @@ static const struct regulator_ops 
rpmh_regulator_vrm_drms_ops = {
.get_mode   = rpmh_regulator_vrm_get_mode,
.get_optimum_mode   = rpmh_regulator_vrm_get_optimum_mode,
 };
 
-static const struct regulator_ops rpmh_regulator_vrm_bypass_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-   .set_voltage_sel= rpmh_regulator_vrm_set_voltage_sel,
-   .get_voltage_sel= rpmh_regulator_vrm_get_voltage_sel,
-   .list_voltage   = regulator_list_voltage_linear_range,
-   .set_mode   = rpmh_regulator_vrm_set_mode,
-   .get_mode   = rpmh_regulator_vrm_get_mode,
-   .set_bypass = rpmh_regulator_vrm_set_bypass,
-   .get_bypass = rpmh_regulator_vrm_get_bypass,
-};
-
-static const struct regulator_ops rpmh_regulator_xob_ops = {
-   .enable = rpmh_regulator_enable,
-   .disable= rpmh_regulator_disable,
-   .is_enabled = rpmh_regulator_is_enabled,
-};
-
-/**
- * rpmh_regulator_init_vreg() - initialize all attributes of an rpmh-regulator
- * @vreg:  Pointer to the individual rpmh-regulator resource
- * @dev:   Pointer to the top level rpmh-regulator PMIC 
device
- * @node:  Pointer to the individual rpmh-regulator resource
- * device node
- * @pmic_id:   String used to identify the top level rpmh-regulator
- * PMIC device on the board
- * @pmic_rpmh_data:Pointer to a null-terminated array of rpmh-regulator
- * resources defined for the top level PMIC device
- *
- * Return: 0 on success, errno on failure
- */
-static int rpmh_regulator_init_vreg(struct rpmh_vreg *vreg, struct device *dev,
-   struct device_node *node, const char *pmic_id,
-   

[PATCH v4 20/21] power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot

2024-07-09 Thread Caleb Connolly
Refactor initialization to use U-Boot's driver model and API.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 136 +++---
 1 file changed, 102 insertions(+), 34 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index b716b380c148..06fd3f31956f 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -411,66 +411,134 @@ static const struct rpmh_vreg_init_data 
pm8150l_vreg_data[] = {
RPMH_VREG("ldo11",  "ldo%s11", _pldo,  "vdd-l7-l11"),
{}
 };
 
-static int rpmh_regulator_probe(struct platform_device *pdev)
+/* probe an individual regulator */
+static int rpmh_regulator_probe(struct udevice *dev)
 {
-   struct device *dev = >dev;
-   const struct rpmh_vreg_init_data *vreg_data;
-   struct device_node *node;
-   struct rpmh_vreg *vreg;
-   const char *pmic_id;
-   int ret;
+   const struct rpmh_vreg_init_data *init_data;
+   struct rpmh_vreg *priv;
+   struct dm_regulator_uclass_plat *plat_data;
 
-   vreg_data = of_device_get_match_data(dev);
-   if (!vreg_data)
+   init_data = (const struct rpmh_vreg_init_data 
*)dev_get_driver_data(dev);
+   priv = dev_get_priv(dev);
+   plat_data = dev_get_uclass_plat(dev);
+
+   priv->dev = dev;
+   priv->addr = cmd_db_read_addr(dev->name);
+   if (!priv->addr) {
+   dev_err(dev, "Failed to read RPMh address for %s\n", dev->name);
return -ENODEV;
-
-   ret = of_property_read_string(dev->of_node, "qcom,pmic-id", _id);
-   if (ret < 0) {
-   dev_err(dev, "qcom,pmic-id missing in DT node\n");
-   return ret;
}
 
-   for_each_available_child_of_node(dev->of_node, node) {
-   vreg = devm_kzalloc(dev, sizeof(*vreg), GFP_KERNEL);
-   if (!vreg) {
-   of_node_put(node);
+   priv->hw_data = init_data->hw_data;
+   priv->enabled = -EINVAL;
+   priv->uv = -ENOTRECOVERABLE;
+   if (ofnode_read_u32(dev_ofnode(dev), "regulator-initial-mode", 
>mode))
+   priv->mode = -EINVAL;
+
+   plat_data->mode = priv->hw_data->pmic_mode_map;
+   plat_data->mode_count = priv->hw_data->n_modes;
+
+   return 0;
+}
+
+/* for non-drm, xob, or bypass regulators add additional driver definitions */
+U_BOOT_DRIVER(rpmh_regulator_drm) = {
+   .name = "rpmh_regulator_drm",
+   .id = UCLASS_REGULATOR,
+   .probe = rpmh_regulator_probe,
+   .priv_auto = sizeof(struct rpmh_vreg),
+   .ops = _regulator_vrm_drms_ops,
+};
+
+/* This driver intentionally only supports a subset of the available 
regulators.
+ * This function checks to see if a given regulator node in DT matches a 
regulator
+ * defined in the driver.
+ */
+static const struct rpmh_vreg_init_data *
+vreg_get_init_data(const struct rpmh_vreg_init_data *init_data, ofnode node)
+{
+   const struct rpmh_vreg_init_data *data;
+
+   for (data = init_data; data->name; data++) {
+   if (!strcmp(data->name, ofnode_get_name(node)))
+   return data;
+   }
+
+   return NULL;
+}
+
+static int rpmh_regulators_bind(struct udevice *dev)
+{
+   const struct rpmh_vreg_init_data *init_data, *data;
+   const char *pmic_id;
+   char *name;
+   struct driver *drv;
+   ofnode node;
+   int ret;
+   size_t namelen;
+
+   init_data = (const struct rpmh_vreg_init_data 
*)dev_get_driver_data(dev);
+   if (!init_data) {
+   dev_err(dev, "No RPMh regulator init data\n");
+   return -ENODEV;
+   }
+
+   pmic_id = ofnode_read_string(dev_ofnode(dev), "qcom,pmic-id");
+   if (!pmic_id) {
+   dev_err(dev, "No PMIC ID\n");
+   return -ENODEV;
+   }
+
+   drv = lists_driver_lookup_name("rpmh_regulator_drm");
+
+   ofnode_for_each_subnode(node, dev_ofnode(dev)) {
+   data = vreg_get_init_data(init_data, node);
+   if (!data)
+   continue;
+
+   /* %s is replaced with pmic_id, so subtract 2, then add 1 for 
the null terminator */
+   namelen = strlen(data->resource_name) + strlen(pmic_id) - 1;
+   name = devm_kzalloc(dev, namelen, GFP_KERNEL);
+   ret = snprintf(name, namelen, data->resource_name, pmic_id);
+   if (ret < 0 || ret >= namelen) {
+   dev_err(dev, "Failed to create RPMh regulator name\n");
return -ENOMEM;
}
 
-   ret = rpmh_regulator_init_vreg(vreg, dev, node, pmic_id,
-   

[PATCH v4 19/21] power: regulator: qcom-rpmh-regulator: port ops to U-Boot

2024-07-09 Thread Caleb Connolly
Port over the regulator ops to U-Boot's regulator API. Add back the
pmic5 mode map using U-Boot dm_regulator_mode API and adjust the
pmic5_pldo and pmic5_pldo_lv definitions. No functional changes.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 158 ++
 1 file changed, 87 insertions(+), 71 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 2a8e8f9ac444..b716b380c148 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -192,87 +192,96 @@ struct rpmh_vreg_init_data {
  *
  * Return: 0 on success, errno on failure
  */
 static int rpmh_regulator_send_request(struct rpmh_vreg *vreg,
-   struct tcs_cmd *cmd, bool wait_for_ack)
+  const struct tcs_cmd *cmd, bool 
wait_for_ack)
 {
int ret;
 
if (wait_for_ack || vreg->always_wait_for_ack)
-   ret = rpmh_write(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd, 1);
+   ret = rpmh_write(vreg->dev->parent, RPMH_ACTIVE_ONLY_STATE, 
cmd, 1);
else
-   ret = rpmh_write_async(vreg->dev, RPMH_ACTIVE_ONLY_STATE, cmd,
-   1);
+   ret = rpmh_write_async(vreg->dev->parent, 
RPMH_ACTIVE_ONLY_STATE, cmd, 1);
 
return ret;
 }
 
-static int _rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev,
-   unsigned int selector, bool wait_for_ack)
+static int _rpmh_regulator_vrm_set_value(struct udevice *rdev,
+int uv, bool wait_for_ack)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
struct tcs_cmd cmd = {
.addr = vreg->addr + RPMH_REGULATOR_REG_VRM_VOLTAGE,
};
int ret;
+   unsigned int selector;
 
-   /* VRM voltage control register is set with voltage in millivolts. */
-   cmd.data = DIV_ROUND_UP(regulator_list_voltage_linear_range(rdev,
-   selector), 1000);
+   selector = (uv - vreg->hw_data->voltage_range.min) / 
vreg->hw_data->voltage_range.step;
+   cmd.data = DIV_ROUND_UP(vreg->hw_data->voltage_range.min +
+   selector * vreg->hw_data->voltage_range.step, 
1000);
 
ret = rpmh_regulator_send_request(vreg, , wait_for_ack);
if (!ret)
-   vreg->voltage_selector = selector;
+   vreg->uv = cmd.data * 1000;
 
return ret;
 }
 
-static int rpmh_regulator_vrm_set_voltage_sel(struct regulator_dev *rdev,
-   unsigned int selector)
+static int rpmh_regulator_vrm_set_value(struct udevice *rdev,
+   int uv)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
+
+   debug("%s: set_value %d (current %d)\n", rdev->name, uv, vreg->uv);
 
if (vreg->enabled == -EINVAL) {
/*
 * Cache the voltage and send it later when the regulator is
 * enabled or disabled.
 */
-   vreg->voltage_selector = selector;
+   vreg->uv = uv;
return 0;
}
 
-   return _rpmh_regulator_vrm_set_voltage_sel(rdev, selector,
-   selector > vreg->voltage_selector);
+   return _rpmh_regulator_vrm_set_value(rdev, uv,
+   uv > vreg->uv);
 }
 
-static int rpmh_regulator_vrm_get_voltage_sel(struct regulator_dev *rdev)
+static int rpmh_regulator_vrm_get_value(struct udevice *rdev)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
 
-   return vreg->voltage_selector;
+   debug("%s: get_value %d\n", rdev->name, vreg->uv);
+
+   return vreg->uv;
 }
 
-static int rpmh_regulator_is_enabled(struct regulator_dev *rdev)
+static int rpmh_regulator_is_enabled(struct udevice *rdev)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
 
-   return vreg->enabled;
+   debug("%s: is_enabled %d\n", rdev->name, vreg->enabled);
+
+   return vreg->enabled > 0;
 }
 
-static int rpmh_regulator_set_enable_state(struct regulator_dev *rdev,
-   bool enable)
+static int rpmh_regulator_set_enable_state(struct udevice *rdev,
+  bool enable)
 {
-   struct rpmh_vreg *vreg = rdev_get_drvdata(rdev);
+   struct rpmh_vreg *vreg = dev_get_priv(rdev);
struct tcs_cmd cmd = {
.add

[PATCH v4 17/21] power: regulator: adjust structs for U-Boot

2024-07-09 Thread Caleb Connolly
Switch to our linear_range helpers and remove unused/unsupported
linux-isms.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 28 +--
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index d0acee9f558e..089623f3a2b9 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -102,13 +102,12 @@ struct linear_range {
  * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
  * @regulator_type:RPMh accelerator type used to manage this
  * regulator
  * @ops:   Pointer to regulator ops callback structure
- * @voltage_ranges:The possible ranges of voltages supported by 
this
- * PMIC regulator type
- * @n_linear_ranges:   Number of entries in voltage_ranges
+ * @voltage_range: The single range of voltages supported by this
+ * PMIC regulator type
  * @n_voltages:The number of unique voltage set points 
defined
- * by voltage_ranges
+ * by voltage_range
  * @hpm_min_load_uA:   Minimum load current in microamps that requires
  * high power mode (HPM) operation.  This is used
  * for LDO hardware type regulators only.
  * @pmic_mode_map: Array indexed by regulator framework mode
@@ -119,15 +118,15 @@ struct linear_range {
  * in device tree to a regulator framework mode
  */
 struct rpmh_vreg_hw_data {
enum rpmh_regulator_typeregulator_type;
-   const struct regulator_ops  *ops;
-   const struct linear_range   *voltage_ranges;
-   int n_linear_ranges;
+   const struct dm_regulator_ops   *ops;
+   struct linear_range voltage_range;
int n_voltages;
int hpm_min_load_uA;
-   const int   *pmic_mode_map;
-   unsigned int  (*of_map_mode)(unsigned int mode);
+   struct dm_regulator_mode*pmic_mode_map;
+   int n_modes;
+   unsigned int(*of_map_mode)(unsigned int 
mode);
 };
 
 /**
  * struct rpmh_vreg - individual RPMh regulator data structure encapsulating a
@@ -148,23 +147,22 @@ struct rpmh_vreg_hw_data {
  * not
  * @bypassed:  Boolean indicating if the regulator is in
  * bypass (pass-through) mode or not.  This is
  * only used by BOB rpmh-regulator resources.
- * @voltage_selector:  Selector used for get_voltage_sel() and
- * set_voltage_sel() callbacks
+ * @uv:Selector used for get_voltage_sel() and
+ * set_value() callbacks
  * @mode:  RPMh VRM regulator current framework mode
  */
 struct rpmh_vreg {
-   struct device   *dev;
+   struct udevice  *dev;
u32 addr;
-   struct regulator_desc   rdesc;
const struct rpmh_vreg_hw_data  *hw_data;
boolalways_wait_for_ack;
 
int enabled;
boolbypassed;
-   int voltage_selector;
-   unsigned intmode;
+   int uv;
+   int mode;
 };
 
 /**
  * struct rpmh_vreg_init_data - initialization data for an RPMh regulator

-- 
2.45.2



[PATCH v4 14/21] power: regulator: import qcom-rpmh-regulator from Linux

2024-07-09 Thread Caleb Connolly
Import the driver from Linux 6.10-rc6.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/Kconfig   |8 +
 drivers/power/regulator/Makefile  |1 +
 drivers/power/regulator/qcom-rpmh-regulator.c | 1709 +
 3 files changed, 1718 insertions(+)

diff --git a/drivers/power/regulator/Kconfig b/drivers/power/regulator/Kconfig
index 102ec7bc5f89..bc061c20d75e 100644
--- a/drivers/power/regulator/Kconfig
+++ b/drivers/power/regulator/Kconfig
@@ -215,8 +215,16 @@ config DM_REGULATOR_GPIO
This config enables implementation of driver-model regulator uclass
features for gpio regulators. The driver implements get/set for
voltage value.
 
+config DM_REGULATOR_QCOM_RPMH
+   bool "Enable driver model for Qualcomm RPMh regulator"
+   depends on DM_REGULATOR && QCOM_RPMH
+   ---help---
+ Enable support for the Qualcomm RPMh regulator. The driver
+ implements get/set api for a limited set of regulators used
+ by u-boot.
+
 config SPL_DM_REGULATOR_GPIO
bool "Enable Driver Model for GPIO REGULATOR in SPL"
depends on DM_REGULATOR_GPIO && SPL_GPIO
select SPL_DM_REGULATOR_COMMON
diff --git a/drivers/power/regulator/Makefile b/drivers/power/regulator/Makefile
index f79932d83307..56a527612b74 100644
--- a/drivers/power/regulator/Makefile
+++ b/drivers/power/regulator/Makefile
@@ -20,8 +20,9 @@ obj-$(CONFIG_$(SPL_)REGULATOR_PWM) += pwm_regulator.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FAN53555) += fan53555.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_COMMON) += regulator_common.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_FIXED) += fixed.o
 obj-$(CONFIG_$(SPL_)DM_REGULATOR_GPIO) += gpio-regulator.o
+obj-$(CONFIG_DM_REGULATOR_QCOM_RPMH) += qcom-rpmh-regulator.o
 obj-$(CONFIG_$(SPL_TPL_)REGULATOR_RK8XX) += rk8xx.o
 obj-$(CONFIG_DM_REGULATOR_S2MPS11) += s2mps11_regulator.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_DM_REGULATOR_SANDBOX) += sandbox.o
diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
new file mode 100644
index ..80e304711345
--- /dev/null
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -0,0 +1,1709 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
+// Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+
+/**
+ * enum rpmh_regulator_type - supported RPMh accelerator types
+ * @VRM:   RPMh VRM accelerator which supports voting on enable, voltage,
+ * and mode of LDO, SMPS, and BOB type PMIC regulators.
+ * @XOB:   RPMh XOB accelerator which supports voting on the enable state
+ * of PMIC regulators.
+ */
+enum rpmh_regulator_type {
+   VRM,
+   XOB,
+};
+
+#define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0
+#define RPMH_REGULATOR_REG_ENABLE  0x4
+#define RPMH_REGULATOR_REG_VRM_MODE0x8
+
+#define PMIC4_LDO_MODE_RETENTION   4
+#define PMIC4_LDO_MODE_LPM 5
+#define PMIC4_LDO_MODE_HPM 7
+
+#define PMIC4_SMPS_MODE_RETENTION  4
+#define PMIC4_SMPS_MODE_PFM5
+#define PMIC4_SMPS_MODE_AUTO   6
+#define PMIC4_SMPS_MODE_PWM7
+
+#define PMIC4_BOB_MODE_PASS0
+#define PMIC4_BOB_MODE_PFM 1
+#define PMIC4_BOB_MODE_AUTO2
+#define PMIC4_BOB_MODE_PWM 3
+
+#define PMIC5_LDO_MODE_RETENTION   3
+#define PMIC5_LDO_MODE_LPM 4
+#define PMIC5_LDO_MODE_HPM 7
+
+#define PMIC5_SMPS_MODE_RETENTION  3
+#define PMIC5_SMPS_MODE_PFM4
+#define PMIC5_SMPS_MODE_AUTO   6
+#define PMIC5_SMPS_MODE_PWM7
+
+#define PMIC5_BOB_MODE_PASS2
+#define PMIC5_BOB_MODE_PFM 4
+#define PMIC5_BOB_MODE_AUTO6
+#define PMIC5_BOB_MODE_PWM 7
+
+/**
+ * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
+ * @regulator_type:RPMh accelerator type used to manage this
+ * regulator
+ * @ops:   Pointer to regulator ops callback structure
+ * @voltage_ranges:The possible ranges of voltages supported by 
this
+ * PMIC regulator type
+ * @n_linear_ranges:   Number of entries in voltage_ranges
+ * @n_voltages:The number of unique voltage set points 
defined
+ * by voltage_ranges
+ * @hpm_min_load_uA:   M

[PATCH v4 16/21] power: regulator: qcom-rpmh-regulator: port over lineage_range helpers

2024-07-09 Thread Caleb Connolly
Import struct linear_range() and builder macro from Linux regulator
core.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 37 +++
 1 file changed, 37 insertions(+)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 5f522de44734..d0acee9f558e 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -28,8 +28,15 @@ enum rpmh_regulator_type {
VRM,
XOB,
 };
 
+enum rpmh_regulator_mode {
+   REGULATOR_MODE_RETENTION,
+   REGULATOR_MODE_LPM,
+   REGULATOR_MODE_AUTO,
+   REGULATOR_MODE_HPM,
+};
+
 #define RPMH_REGULATOR_REG_VRM_VOLTAGE 0x0
 #define RPMH_REGULATOR_REG_ENABLE  0x4
 #define RPMH_REGULATOR_REG_VRM_MODE0x8
 
@@ -60,8 +67,38 @@ enum rpmh_regulator_type {
 #define PMIC5_BOB_MODE_PFM 4
 #define PMIC5_BOB_MODE_AUTO6
 #define PMIC5_BOB_MODE_PWM 7
 
+
+/**
+ * struct linear_range - table of selector - value pairs
+ *
+ * Define a lookup-table for range of values. Intended to help when looking
+ * for a register value matching certaing physical measure (like voltage).
+ * Usable when increment of one in register always results a constant increment
+ * of the physical measure (like voltage).
+ *
+ * @min:  Lowest value in range
+ * @min_sel: Lowest selector for range
+ * @max_sel: Highest selector for range
+ * @step: Value step size
+ */
+struct linear_range {
+   unsigned int min;
+   unsigned int min_sel;
+   unsigned int max_sel;
+   unsigned int step;
+};
+
+/* Initialize struct linear_range for regulators */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)  \
+{  \
+   .min= _min_uV,  \
+   .min_sel= _min_sel, \
+   .max_sel= _max_sel, \
+   .step   = _step_uV, \
+}
+
 /**
  * struct rpmh_vreg_hw_data - RPMh regulator hardware configurations
  * @regulator_type:RPMh accelerator type used to manage this
  * regulator

-- 
2.45.2



[PATCH v4 15/21] power: regulator: adjust headers for U-Boot

2024-07-09 Thread Caleb Connolly
Remove unused/unsupported Linux headers and add necessary U-Boot ones.

Signed-off-by: Caleb Connolly 
---
 drivers/power/regulator/qcom-rpmh-regulator.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/power/regulator/qcom-rpmh-regulator.c 
b/drivers/power/regulator/qcom-rpmh-regulator.c
index 80e304711345..5f522de44734 100644
--- a/drivers/power/regulator/qcom-rpmh-regulator.c
+++ b/drivers/power/regulator/qcom-rpmh-regulator.c
@@ -4,17 +4,14 @@
 
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
 

-- 
2.45.2



[PATCH v4 07/21] soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS support

2024-07-09 Thread Caleb Connolly
Since U-Boot is single threaded, we can avoid most of the complexity
that comes with handling more than one in-flight TCS. Drop all the rpmh
code associated with multi-threading as we'll instead wait for a
response on each TCS.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-internal.h |   4 -
 drivers/soc/qcom/rpmh-rsc.c  | 562 ---
 2 files changed, 566 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
index e3cf1beff803..12c5b8d9cf86 100644
--- a/drivers/soc/qcom/rpmh-internal.h
+++ b/drivers/soc/qcom/rpmh-internal.h
@@ -139,10 +139,6 @@ struct rsc_drv {
 int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg);
 int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv,
 const struct tcs_request *msg);
 void rpmh_rsc_invalidate(struct rsc_drv *drv);
-void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv);
-
-void rpmh_tx_done(const struct tcs_request *msg);
-int rpmh_flush(struct rpmh_ctrlr *ctrlr);
 
 #endif /* __RPM_INTERNAL_H__ */
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index de86009ecd91..fc8321bf208f 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -246,49 +246,8 @@ static void write_tcs_reg_sync(const struct rsc_drv *drv, 
int reg, int tcs_id,
pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
   data, tcs_id, reg);
 }
 
-/**
- * tcs_invalidate() - Invalidate all TCSes of the given type (sleep or wake).
- * @drv:  The RSC controller.
- * @type: SLEEP_TCS or WAKE_TCS
- *
- * This will clear the "slots" variable of the given tcs_group and also
- * tell the hardware to forget about all entries.
- *
- * The caller must ensure that no other RPMH actions are happening when this
- * function is called, since otherwise the device may immediately become
- * used again even before this function exits.
- */
-static void tcs_invalidate(struct rsc_drv *drv, int type)
-{
-   int m;
-   struct tcs_group *tcs = >tcs[type];
-
-   /* Caller ensures nobody else is running so no lock */
-   if (bitmap_empty(tcs->slots, MAX_TCS_SLOTS))
-   return;
-
-   for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++)
-   write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], m, 0);
-
-   bitmap_zero(tcs->slots, MAX_TCS_SLOTS);
-}
-
-/**
- * rpmh_rsc_invalidate() - Invalidate sleep and wake TCSes.
- * @drv: The RSC controller.
- *
- * The caller must ensure that no other RPMH actions are happening when this
- * function is called, since otherwise the device may immediately become
- * used again even before this function exits.
- */
-void rpmh_rsc_invalidate(struct rsc_drv *drv)
-{
-   tcs_invalidate(drv, SLEEP_TCS);
-   tcs_invalidate(drv, WAKE_TCS);
-}
-
 /**
  * get_tcs_for_msg() - Get the tcs_group used to send the given message.
  * @drv: The RSC controller.
  * @msg: The message we want to send.
@@ -331,158 +290,8 @@ static struct tcs_group *get_tcs_for_msg(struct rsc_drv 
*drv,
 
return tcs;
 }
 
-/**
- * get_req_from_tcs() - Get a stashed request that was xfering on the given 
TCS.
- * @drv:The RSC controller.
- * @tcs_id: The global ID of this TCS.
- *
- * For ACTIVE_ONLY transfers we want to call back into the client when the
- * transfer finishes. To do this we need the "request" that the client
- * originally provided us. This function grabs the request that we stashed
- * when we started the transfer.
- *
- * This only makes sense for ACTIVE_ONLY transfers since those are the only
- * ones we track sending (the only ones we enable interrupts for and the only
- * ones we call back to the client for).
- *
- * Return: The stashed request.
- */
-static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv,
- int tcs_id)
-{
-   struct tcs_group *tcs;
-   int i;
-
-   for (i = 0; i < TCS_TYPE_NR; i++) {
-   tcs = >tcs[i];
-   if (tcs->mask & BIT(tcs_id))
-   return tcs->req[tcs_id - tcs->offset];
-   }
-
-   return NULL;
-}
-
-/**
- * __tcs_set_trigger() - Start xfer on a TCS or unset trigger on a borrowed TCS
- * @drv: The controller.
- * @tcs_id:  The global ID of this TCS.
- * @trigger: If true then untrigger/retrigger. If false then just untrigger.
- *
- * In the normal case we only ever call with "trigger=true" to start a
- * transfer. That will un-trigger/disable the TCS from the last transfer
- * then trigger/enable for this transfer.
- *
- * If we borrowed a wake TCS for an active-only transfer we'll also call
- * this function with "trigger=false" to just do the un-trigger/disable
- * before using the TCS for wake purposes again.
- *
- * Note that the AP is only in charge of triggering active-only transfers.
- * 

[PATCH v4 13/21] soc: qcom: rpmh: U-Boot API changes

2024-07-09 Thread Caleb Connolly
Fix build errors, add some debug logging.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 53 +++--
 include/soc/qcom/rpmh.h |  4 ++--
 2 files changed, 22 insertions(+), 35 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 22605e0291a1..96f14a9afdf2 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -15,27 +15,30 @@
 #include "rpmh-internal.h"
 
 #define RPMH_TIMEOUT_MSmsecs_to_jiffies(1)
 
-#define DEFINE_RPMH_MSG_ONSTACK(device, s, q, name)\
+#define DEFINE_RPMH_MSG_ONSTACK(device, s, name)   \
struct rpmh_request name = {\
.msg = {\
.state = s, \
.cmds = name.cmd,   \
.num_cmds = 0,  \
-   .wait_for_compl = true, \
},  \
.cmd = { { 0 } },   \
-   .completion = q,\
.dev = device,  \
-   .needs_free = false,\
+   .needs_free = false,\
}
 
 #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
 
-static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
+static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct udevice *dev)
 {
-   struct rsc_drv *drv = dev_get_drvdata(dev->parent);
+   struct rsc_drv *drv = (struct rsc_drv *)dev_get_priv(dev->parent);
+
+   if (!drv) {
+   log_err("BUG: no RPMh driver for %s (parent %s)\n", dev->name, 
dev->parent->name);
+   BUG();
+   }
 
return >client;
 }
 
@@ -49,36 +52,23 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct 
device *dev)
  * Cache the RPMH request and send if the state is ACTIVE_ONLY.
  * SLEEP/WAKE_ONLY requests are not sent to the controller at
  * this time. Use rpmh_flush() to send them to the controller.
  */
-static int __rpmh_write(const struct device *dev, enum rpmh_state state,
+static int __rpmh_write(const struct udevice *dev, enum rpmh_state state,
struct rpmh_request *rpm_msg)
 {
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
-   int ret = -EINVAL;
-   struct cache_req *req;
-   int i;
 
-   /* Cache the request in our store and link the payload */
-   for (i = 0; i < rpm_msg->msg.num_cmds; i++) {
-   req = cache_rpm_request(ctrlr, state, _msg->msg.cmds[i]);
-   if (IS_ERR(req))
-   return PTR_ERR(req);
+   if (state != RPMH_ACTIVE_ONLY_STATE) {
+   log_err("only ACTIVE_ONLY state supported\n");
+   return -EINVAL;
}
 
-   if (state == RPMH_ACTIVE_ONLY_STATE) {
-   ret = rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), _msg->msg);
-   } else {
-   /* Clean up our call by spoofing tx_done */
-   ret = 0;
-   rpmh_tx_done(_msg->msg);
-   }
-
-   return ret;
+   return rpmh_rsc_send_data(ctrlr_to_drv(ctrlr), _msg->msg);
 }
 
 static int __fill_rpmh_msg(struct rpmh_request *req, enum rpmh_state state,
-   const struct tcs_cmd *cmd, u32 n)
+  const struct tcs_cmd *cmd, u32 n)
 {
if (!cmd || !n || n > MAX_RPMH_PAYLOAD)
return -EINVAL;
 
@@ -87,8 +77,10 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
req->msg.state = state;
req->msg.cmds = req->cmd;
req->msg.num_cmds = n;
 
+   debug("rpmh_msg: %d, %d cmds [first %#x/%#x]\n", state, n, cmd->addr, 
cmd->data);
+
return 0;
 }
 
 /**
@@ -100,24 +92,19 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
  * @n: The number of elements in @cmd
  *
  * May sleep. Do not call from atomic contexts.
  */
-int rpmh_write(const struct device *dev, enum rpmh_state state,
+int rpmh_write(const struct udevice *dev, enum rpmh_state state,
   const struct tcs_cmd *cmd, u32 n)
 {
-   DECLARE_COMPLETION_ONSTACK(compl);
-   DEFINE_RPMH_MSG_ONSTACK(dev, state, , rpm_msg);
+   DEFINE_RPMH_MSG_ONSTACK(dev, state, rpm_msg);
int ret;
 
ret = __fill_rpmh_msg(_msg, state, cmd, n);
if (ret)
return ret;
 
ret = __rpmh_write(dev, state, _msg);
-   if (ret)
-   return ret;
 
-   ret = wait_for_completion_timeout(, RPMH_TIMEOUT_MS);
-   WARN_ON(!ret);
-   return (ret > 0) ? 0 : -ETIMEDOUT;
+   return ret;
 }
 EXPORT_SYMBOL_GPL(rpmh_write);
diff --git a/include/soc/qcom/rpmh.h b/include/soc/qcom/rpmh.h

[PATCH v4 12/21] soc: qcom: rpmh: drop unused functions

2024-07-09 Thread Caleb Connolly
A lot of the features in here are only relevant when running
multi-threaded with interrupts. Drop everything except what we need to
run single-threaded with a single TCS (which is all the rpmh-rsc
framework in U-Boot supports).

Keep rpmh_write_async() for simplicity and make it wrap the regular
rpmh_write().

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 371 
 include/soc/qcom/rpmh.h |  25 +---
 2 files changed, 3 insertions(+), 393 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 03ef4106c9a6..22605e0291a1 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -31,124 +31,15 @@
}
 
 #define ctrlr_to_drv(ctrlr) container_of(ctrlr, struct rsc_drv, client)
 
-/**
- * struct cache_req: the request object for caching
- *
- * @addr: the address of the resource
- * @sleep_val: the sleep vote
- * @wake_val: the wake vote
- * @list: linked list obj
- */
-struct cache_req {
-   u32 addr;
-   u32 sleep_val;
-   u32 wake_val;
-   struct list_head list;
-};
-
-/**
- * struct batch_cache_req - An entry in our batch catch
- *
- * @list: linked list obj
- * @count: number of messages
- * @rpm_msgs: the messages
- */
-
-struct batch_cache_req {
-   struct list_head list;
-   int count;
-   struct rpmh_request rpm_msgs[];
-};
-
 static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev)
 {
struct rsc_drv *drv = dev_get_drvdata(dev->parent);
 
return >client;
 }
 
-void rpmh_tx_done(const struct tcs_request *msg)
-{
-   struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request,
-   msg);
-   struct completion *compl = rpm_msg->completion;
-   bool free = rpm_msg->needs_free;
-
-   if (!compl)
-   goto exit;
-
-   /* Signal the blocking thread we are done */
-   complete(compl);
-
-exit:
-   if (free)
-   kfree(rpm_msg);
-}
-
-static struct cache_req *__find_req(struct rpmh_ctrlr *ctrlr, u32 addr)
-{
-   struct cache_req *p, *req = NULL;
-
-   list_for_each_entry(p, >cache, list) {
-   if (p->addr == addr) {
-   req = p;
-   break;
-   }
-   }
-
-   return req;
-}
-
-static struct cache_req *cache_rpm_request(struct rpmh_ctrlr *ctrlr,
-  enum rpmh_state state,
-  struct tcs_cmd *cmd)
-{
-   struct cache_req *req;
-   unsigned long flags;
-   u32 old_sleep_val, old_wake_val;
-
-   spin_lock_irqsave(>cache_lock, flags);
-   req = __find_req(ctrlr, cmd->addr);
-   if (req)
-   goto existing;
-
-   req = kzalloc(sizeof(*req), GFP_ATOMIC);
-   if (!req) {
-   req = ERR_PTR(-ENOMEM);
-   goto unlock;
-   }
-
-   req->addr = cmd->addr;
-   req->sleep_val = req->wake_val = UINT_MAX;
-   list_add_tail(>list, >cache);
-
-existing:
-   old_sleep_val = req->sleep_val;
-   old_wake_val = req->wake_val;
-
-   switch (state) {
-   case RPMH_ACTIVE_ONLY_STATE:
-   case RPMH_WAKE_ONLY_STATE:
-   req->wake_val = cmd->data;
-   break;
-   case RPMH_SLEEP_STATE:
-   req->sleep_val = cmd->data;
-   break;
-   }
-
-   ctrlr->dirty |= (req->sleep_val != old_sleep_val ||
-req->wake_val != old_wake_val) &&
-req->sleep_val != UINT_MAX &&
-req->wake_val != UINT_MAX;
-
-unlock:
-   spin_unlock_irqrestore(>cache_lock, flags);
-
-   return req;
-}
-
 /**
  * __rpmh_write: Cache and send the RPMH request
  *
  * @dev: The device making the request
@@ -199,40 +90,8 @@ static int __fill_rpmh_msg(struct rpmh_request *req, enum 
rpmh_state state,
 
return 0;
 }
 
-/**
- * rpmh_write_async: Write a set of RPMH commands
- *
- * @dev: The device making the request
- * @state: Active/sleep set
- * @cmd: The payload data
- * @n: The number of elements in payload
- *
- * Write a set of RPMH commands, the order of commands is maintained
- * and will be sent as a single shot.
- */
-int rpmh_write_async(const struct device *dev, enum rpmh_state state,
-const struct tcs_cmd *cmd, u32 n)
-{
-   struct rpmh_request *rpm_msg;
-   int ret;
-
-   rpm_msg = kzalloc(sizeof(*rpm_msg), GFP_ATOMIC);
-   if (!rpm_msg)
-   return -ENOMEM;
-   rpm_msg->needs_free = true;
-
-   ret = __fill_rpmh_msg(rpm_msg, state, cmd, n);
-   if (ret) {
-   kfree(rpm_msg);
-   return ret;
-   }
-
-   return __rpmh_write(dev, state, rpm_msg);
-}
-EXPORT_SYMBOL_GPL(rpmh_write_async);
-
 /**
  * rpmh_write: Write a set of RPMH

[PATCH v4 11/21] soc: qcom: rpmh: adjust headers for U-Boot

2024-07-09 Thread Caleb Connolly
Drop unused/unsupported Linux headers and add dm/device.h for U-Boot.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh.c | 12 ++--
 1 file changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 8903ed956312..03ef4106c9a6 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -2,22 +2,14 @@
 /*
  * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  */
 
-#include 
+#include 
+#include 
 #include 
-#include 
-#include 
 #include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
 #include 
-#include 
 
 #include 
 
 #include "rpmh-internal.h"

-- 
2.45.2



[PATCH v4 09/21] soc: qcom: rpmh-rsc: adjust probe for U-Boot

2024-07-09 Thread Caleb Connolly
Rework the rpmh-rsc initialization to use U-Boot's driver model and
initialize cmd-db.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-internal.h |  14 ++--
 drivers/soc/qcom/rpmh-rsc.c  | 143 +--
 2 files changed, 50 insertions(+), 107 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h
index 12c5b8d9cf86..ac8f6c35a7a4 100644
--- a/drivers/soc/qcom/rpmh-internal.h
+++ b/drivers/soc/qcom/rpmh-internal.h
@@ -7,17 +7,18 @@
 #ifndef __RPM_INTERNAL_H__
 #define __RPM_INTERNAL_H__
 
 #include 
-#include 
 #include 
 
 #define TCS_TYPE_NR4
 #define MAX_CMDS_PER_TCS   16
 #define MAX_TCS_PER_TYPE   3
 #define MAX_TCS_NR (MAX_TCS_PER_TYPE * TCS_TYPE_NR)
 #define MAX_TCS_SLOTS  (MAX_CMDS_PER_TCS * MAX_TCS_PER_TYPE)
 
+#define USEC_PER_SEC   100UL
+
 struct rsc_drv;
 
 /**
  * struct tcs_group: group of Trigger Command Sets (TCS) to send state requests
@@ -63,10 +64,9 @@ struct tcs_group {
  */
 struct rpmh_request {
struct tcs_request msg;
struct tcs_cmd cmd[MAX_RPMH_PAYLOAD];
-   struct completion *completion;
-   const struct device *dev;
+   const struct udevice *dev;
bool needs_free;
 };
 
 /**
@@ -78,9 +78,8 @@ struct rpmh_request {
  * @batch_cache: Cache sleep and wake requests sent as batch
  */
 struct rpmh_ctrlr {
struct list_head cache;
-   spinlock_t cache_lock;
bool dirty;
struct list_head batch_cache;
 };
 
@@ -122,17 +121,12 @@ struct rsc_drv {
void __iomem *base;
void __iomem *tcs_base;
int id;
int num_tcs;
-   struct notifier_block rsc_pm;
-   struct notifier_block genpd_nb;
-   atomic_t cpus_in_pm;
struct tcs_group tcs[TCS_TYPE_NR];
DECLARE_BITMAP(tcs_in_use, MAX_TCS_NR);
-   spinlock_t lock;
-   wait_queue_head_t tcs_wait;
struct rpmh_ctrlr client;
-   struct device *dev;
+   struct udevice *dev;
struct rsc_ver ver;
u32 *regs;
 };
 
diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index c09214552cfb..d4ef88dda184 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -386,20 +386,20 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct 
tcs_request *msg)
 
return 0;
 }
 
-static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv 
*drv)
+static int rpmh_probe_tcs_config(struct udevice *dev, struct rsc_drv *drv)
 {
struct tcs_type_config {
u32 type;
u32 n;
} tcs_cfg[TCS_TYPE_NR] = { { 0 } };
-   struct device_node *dn = pdev->dev.of_node;
+   ofnode dn = dev_ofnode(dev);
u32 config, max_tcs, ncpt, offset;
int i, ret, n, st = 0;
struct tcs_group *tcs;
 
-   ret = of_property_read_u32(dn, "qcom,tcs-offset", );
+   ret = ofnode_read_u32(dn, "qcom,tcs-offset", );
if (ret)
return ret;
drv->tcs_base = drv->base + offset;
 
@@ -411,24 +411,15 @@ static int rpmh_probe_tcs_config(struct platform_device 
*pdev, struct rsc_drv *d
 
ncpt = config & (DRV_NCPT_MASK << DRV_NCPT_SHIFT);
ncpt = ncpt >> DRV_NCPT_SHIFT;
 
-   n = of_property_count_u32_elems(dn, "qcom,tcs-config");
-   if (n != 2 * TCS_TYPE_NR)
-   return -EINVAL;
+   n = ofnode_read_u32_array(dn, "qcom,tcs-config", (u32 *)tcs_cfg, 2 * 
TCS_TYPE_NR);
+   if (n < 0) {
+   log_err("RPMh: %s: error reading qcom,tcs-config %d\n", 
dev->name, n);
+   return n;
+   }
 
for (i = 0; i < TCS_TYPE_NR; i++) {
-   ret = of_property_read_u32_index(dn, "qcom,tcs-config",
-i * 2, _cfg[i].type);
-   if (ret)
-   return ret;
-   if (tcs_cfg[i].type >= TCS_TYPE_NR)
-   return -EINVAL;
-
-   ret = of_property_read_u32_index(dn, "qcom,tcs-config",
-i * 2 + 1, _cfg[i].n);
-   if (ret)
-   return ret;
if (tcs_cfg[i].n > MAX_TCS_PER_TYPE)
return -EINVAL;
}
 
@@ -457,43 +448,39 @@ static int rpmh_probe_tcs_config(struct platform_device 
*pdev, struct rsc_drv *d
 
return 0;
 }
 
-static int rpmh_rsc_probe(struct platform_device *pdev)
+static int rpmh_rsc_bind(struct udevice *dev)
 {
-   struct device_node *dn = pdev->dev.of_node;
-   struct rsc_drv *drv;
-   char drv_id[10] = {0};
-   int ret, irq;
-   u32 solver_config;
-   u32 rsc_id;
+   int ret;
 
-   /*
-* Even though RPMh doesn't directly use cmd-db, all of its children

[PATCH v4 08/21] soc: qcom: rpmh-rsc: adjust headers for U-Boot

2024-07-09 Thread Caleb Connolly
Remove unsupported / unused Linux headers and add those needed for
U-Boot.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/rpmh-rsc.c | 35 ---
 1 file changed, 12 insertions(+), 23 deletions(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index fc8321bf208f..c09214552cfb 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -5,39 +5,28 @@
  */
 
 #define pr_fmt(fmt) "%s " fmt, KBUILD_MODNAME
 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
 
-#include 
 #include 
 #include 
 #include 
 
 #include "rpmh-internal.h"
 
-#define CREATE_TRACE_POINTS
-#include "trace-rpmh.h"
-
 
 #define RSC_DRV_ID 0
 
 #define MAJOR_VER_MASK 0xFF

-- 
2.45.2



[PATCH v4 06/21] soc: qcom: cmd-db: adjust for U-Boot API

2024-07-09 Thread Caleb Connolly
Keep the header pointer in the .data section so we don't initialize it
again after relocation, adjust cmd_db_get_header() to work with the
U-Boot API, and skip validating the header since all cmd-db users are
children of the rpmh-rsc and those children will only probe if cmd-db
initializes successfully.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index 4d3fd4db8852..b852a269ae12 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -104,9 +104,9 @@ static bool cmd_db_magic_matches(const struct cmd_db_header 
*header)
 
return memcmp(magic, CMD_DB_MAGIC, ARRAY_SIZE(CMD_DB_MAGIC)) == 0;
 }
 
-static struct cmd_db_header *cmd_db_header;
+static struct cmd_db_header *cmd_db_header __section(".data") = NULL;
 
 static inline const void *rsc_to_entry_header(const struct rsc_hdr *hdr)
 {
u16 offset = le16_to_cpu(hdr->header_offset);
@@ -127,16 +127,12 @@ static int cmd_db_get_header(const char *id, const struct 
entry_header **eh,
 const struct rsc_hdr **rh)
 {
const struct rsc_hdr *rsc_hdr;
const struct entry_header *ent;
-   int ret, i, j;
+   int i, j;
u8 query[sizeof(ent->id)] __nonstring;
 
-   ret = cmd_db_ready();
-   if (ret)
-   return ret;
-
-   strtomem_pad(query, id, 0);
+   strncpy(query, id, sizeof(query));
 
for (i = 0; i < MAX_SLV_ID; i++) {
rsc_hdr = _db_header->header[i];
if (!rsc_hdr->slv_id)

-- 
2.45.2



[PATCH v4 05/21] soc: qcom: cmd-db: replace cmd_db_ready() with cmd_db_init()

2024-07-09 Thread Caleb Connolly
Using the driver model for cmd-db is fine, but it's unnecessary
complexity which we can just avoid in U-Boot. Instead let's just have a
function to initialize it and call said function when initializing rpmh.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 74 ++-
 include/soc/qcom/cmd-db.h |  4 +--
 2 files changed, 24 insertions(+), 54 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index b6426ac3cafc..4d3fd4db8852 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -122,24 +122,8 @@ rsc_offset(const struct rsc_hdr *hdr, const struct 
entry_header *ent)
 
return cmd_db_header->data + offset + loffset;
 }
 
-/**
- * cmd_db_ready - Indicates if command DB is available
- *
- * Return: 0 on success, errno otherwise
- */
-int cmd_db_ready(void)
-{
-   if (cmd_db_header == NULL)
-   return -EPROBE_DEFER;
-   else if (!cmd_db_magic_matches(cmd_db_header))
-   return -EINVAL;
-
-   return 0;
-}
-EXPORT_SYMBOL_GPL(cmd_db_ready);
-
 static int cmd_db_get_header(const char *id, const struct entry_header **eh,
 const struct rsc_hdr **rh)
 {
const struct rsc_hdr *rsc_hdr;
@@ -193,55 +177,41 @@ u32 cmd_db_read_addr(const char *id)
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
 EXPORT_SYMBOL_GPL(cmd_db_read_addr);
 
-static int cmd_db_dev_probe(struct platform_device *pdev)
+int cmd_db_init(void)
 {
-   struct reserved_mem *rmem;
-   int ret = 0;
+   void __iomem *base;
+   ofnode rmem, node;
 
-   rmem = of_reserved_mem_lookup(pdev->dev.of_node);
-   if (!rmem) {
-   dev_err(>dev, "failed to acquire memory region\n");
-   return -EINVAL;
+   if (cmd_db_header)
+   return 0;
+
+   rmem = ofnode_path("/reserved-memory");
+   ofnode_for_each_subnode(node, rmem) {
+   if (ofnode_device_is_compatible(node, "qcom,cmd-db"))
+   goto found;
}
 
-   cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
-   if (!cmd_db_header) {
-   ret = -ENOMEM;
-   cmd_db_header = NULL;
-   return ret;
+   log_err("%s: Failed to find cmd-db node\n", __func__);
+   return -ENOENT;
+found:
+   debug("%s(%s)\n", __func__, ofnode_get_name(node));
+
+   base = (void __iomem *)ofnode_get_addr(node);
+   if ((fdt_addr_t)base == FDT_ADDR_T_NONE) {
+   log_err("%s: Failed to read base address\n", __func__);
+   return -ENOENT;
}
 
+   cmd_db_header = base;
if (!cmd_db_magic_matches(cmd_db_header)) {
-   dev_err(>dev, "Invalid Command DB Magic\n");
+   log_err("%s: Invalid Command DB Magic\n", __func__);
return -EINVAL;
}
 
-   device_set_pm_not_required(>dev);
-
return 0;
 }
-
-static const struct of_device_id cmd_db_match_table[] = {
-   { .compatible = "qcom,cmd-db" },
-   { }
-};
-MODULE_DEVICE_TABLE(of, cmd_db_match_table);
-
-static struct platform_driver cmd_db_dev_driver = {
-   .probe  = cmd_db_dev_probe,
-   .driver = {
-  .name = "cmd-db",
-  .of_match_table = cmd_db_match_table,
-  .suppress_bind_attrs = true,
-   },
-};
-
-static int __init cmd_db_device_init(void)
-{
-   return platform_driver_register(_db_dev_driver);
-}
-core_initcall(cmd_db_device_init);
+EXPORT_SYMBOL(cmd_db_init);
 
 MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Command DB Driver");
 MODULE_LICENSE("GPL v2");
diff --git a/include/soc/qcom/cmd-db.h b/include/soc/qcom/cmd-db.h
index 753c7923f8e5..535164cc7fb0 100644
--- a/include/soc/qcom/cmd-db.h
+++ b/include/soc/qcom/cmd-db.h
@@ -21,13 +21,13 @@ enum cmd_db_hw_type {
 
 #if IS_ENABLED(CONFIG_QCOM_COMMAND_DB)
 u32 cmd_db_read_addr(const char *resource_id);
 
-int cmd_db_ready(void);
+int cmd_db_init(void);
 #else
 static inline u32 cmd_db_read_addr(const char *resource_id)
 { return 0; }
 
-static inline int cmd_db_ready(void)
+static inline int cmd_db_init(void)
 { return -ENODEV; }
 #endif /* CONFIG_QCOM_COMMAND_DB */
 #endif /* __QCOM_COMMAND_DB_H__ */

-- 
2.45.2



[PATCH v4 04/21] soc: qcom: cmd-db: drop unused functions

2024-07-09 Thread Caleb Connolly
Due to our simpler rpmh-rsc driver and lack of debugfs, we don't need
quite a few cmd-db functions, just drop them.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 144 --
 include/soc/qcom/cmd-db.h |  15 -
 2 files changed, 159 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index 685b6d530136..b6426ac3cafc 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -193,150 +193,8 @@ u32 cmd_db_read_addr(const char *id)
return ret < 0 ? 0 : le32_to_cpu(ent->addr);
 }
 EXPORT_SYMBOL_GPL(cmd_db_read_addr);
 
-/**
- * cmd_db_read_aux_data() - Query command db for aux data.
- *
- *  @id: Resource to retrieve AUX Data on
- *  @len: size of data buffer returned
- *
- *  Return: pointer to data on success, error pointer otherwise
- */
-const void *cmd_db_read_aux_data(const char *id, size_t *len)
-{
-   int ret;
-   const struct entry_header *ent;
-   const struct rsc_hdr *rsc_hdr;
-
-   ret = cmd_db_get_header(id, , _hdr);
-   if (ret)
-   return ERR_PTR(ret);
-
-   if (len)
-   *len = le16_to_cpu(ent->len);
-
-   return rsc_offset(rsc_hdr, ent);
-}
-EXPORT_SYMBOL_GPL(cmd_db_read_aux_data);
-
-/**
- * cmd_db_match_resource_addr() - Compare if both Resource addresses are same
- *
- * @addr1: Resource address to compare
- * @addr2: Resource address to compare
- *
- * Return: true if two addresses refer to the same resource, false otherwise
- */
-bool cmd_db_match_resource_addr(u32 addr1, u32 addr2)
-{
-   /*
-* Each RPMh VRM accelerator resource has 3 or 4 contiguous 4-byte
-* aligned addresses associated with it. Ignore the offset to check
-* for VRM requests.
-*/
-   if (addr1 == addr2)
-   return true;
-   else if (SLAVE_ID(addr1) == CMD_DB_HW_VRM && VRM_ADDR(addr1) == 
VRM_ADDR(addr2))
-   return true;
-
-   return false;
-}
-EXPORT_SYMBOL_GPL(cmd_db_match_resource_addr);
-
-/**
- * cmd_db_read_slave_id - Get the slave ID for a given resource address
- *
- * @id: Resource id to query the DB for version
- *
- * Return: cmd_db_hw_type enum on success, CMD_DB_HW_INVALID on error
- */
-enum cmd_db_hw_type cmd_db_read_slave_id(const char *id)
-{
-   int ret;
-   const struct entry_header *ent;
-   u32 addr;
-
-   ret = cmd_db_get_header(id, , NULL);
-   if (ret < 0)
-   return CMD_DB_HW_INVALID;
-
-   addr = le32_to_cpu(ent->addr);
-   return (addr >> SLAVE_ID_SHIFT) & SLAVE_ID_MASK;
-}
-EXPORT_SYMBOL_GPL(cmd_db_read_slave_id);
-
-#ifdef CONFIG_DEBUG_FS
-static int cmd_db_debugfs_dump(struct seq_file *seq, void *p)
-{
-   int i, j;
-   const struct rsc_hdr *rsc;
-   const struct entry_header *ent;
-   const char *name;
-   u16 len, version;
-   u8 major, minor;
-
-   seq_puts(seq, "Command DB DUMP\n");
-
-   for (i = 0; i < MAX_SLV_ID; i++) {
-   rsc = _db_header->header[i];
-   if (!rsc->slv_id)
-   break;
-
-   switch (le16_to_cpu(rsc->slv_id)) {
-   case CMD_DB_HW_ARC:
-   name = "ARC";
-   break;
-   case CMD_DB_HW_VRM:
-   name = "VRM";
-   break;
-   case CMD_DB_HW_BCM:
-   name = "BCM";
-   break;
-   default:
-   name = "Unknown";
-   break;
-   }
-
-   version = le16_to_cpu(rsc->version);
-   major = version >> 8;
-   minor = version;
-
-   seq_printf(seq, "Slave %s (v%u.%u)\n", name, major, minor);
-   seq_puts(seq, "-\n");
-
-   ent = rsc_to_entry_header(rsc);
-   for (j = 0; j < le16_to_cpu(rsc->cnt); j++, ent++) {
-   seq_printf(seq, "0x%05x: %*pEp", le32_to_cpu(ent->addr),
-  (int)strnlen(ent->id, sizeof(ent->id)), 
ent->id);
-
-   len = le16_to_cpu(ent->len);
-   if (len) {
-   seq_printf(seq, " [%*ph]",
-  len, rsc_offset(rsc, ent));
-   }
-   seq_putc(seq, '\n');
-   }
-   }
-
-   return 0;
-}
-
-static int open_cmd_db_debugfs(struct inode *inode, struct file *file)
-{
-   return single_open(file, cmd_db_debugfs_dump, inode->i_private);
-}
-#endif
-
-static const struct file_operations cmd_db_debugfs_ops = {
-#ifdef CONFIG_DEBUG_FS
-   .open = open_cmd_db_debugfs,
-#endif
-   .read = seq_read,
-   .llseek = 

[PATCH v4 02/21] soc: qcom: import rpmh and cmd-db drivers from Linux

2024-07-09 Thread Caleb Connolly
Import RPMh and cmd-db framework from Linux 6.10-rc6.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/Kconfig  |1 +
 drivers/soc/Makefile |1 +
 drivers/soc/qcom/Kconfig |   27 +
 drivers/soc/qcom/Makefile|4 +
 drivers/soc/qcom/cmd-db.c|  393 +
 drivers/soc/qcom/rpmh-internal.h |  148 +
 drivers/soc/qcom/rpmh-rsc.c  | 1162 ++
 drivers/soc/qcom/rpmh.c  |  502 
 include/soc/qcom/cmd-db.h|   48 ++
 include/soc/qcom/rpmh.h  |   47 ++
 include/soc/qcom/tcs.h   |   81 +++
 11 files changed, 2414 insertions(+)

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cee506fe4747..8ef408d9ba1b 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -47,8 +47,9 @@ config SOC_XILINX_VERSAL_NET
  Enable this option to select SoC device id driver for Xilinx Versal 
NET.
  This allows other drivers to verify the SoC familiy & revision using
  matching SoC attributes.
 
+source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/samsung/Kconfig"
 source "drivers/soc/ti/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ec89a053165..00e6a5ac8e2b 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,8 +2,9 @@
 #
 # Makefile for the U-Boot SOC specific device drivers.
 
 obj-$(CONFIG_SOC_AMD_VERSAL2) += soc_amd_versal2.o
+obj-$(CONFIG_SOC_QCOM) += qcom/
 obj-$(CONFIG_SOC_SAMSUNG) += samsung/
 obj-$(CONFIG_SOC_TI) += ti/
 obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
 obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
new file mode 100644
index ..4aa7833930c7
--- /dev/null
+++ b/drivers/soc/qcom/Kconfig
@@ -0,0 +1,27 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# QCOM Soc drivers
+#
+menuconfig SOC_QCOM
+   bool "Qualcomm SOC drivers support"
+   help
+ Say Y here if you want to enable Qualcomm SOC drivers support.
+
+if SOC_QCOM
+
+config QCOM_COMMAND_DB
+   bool "Qualcomm Command DB"
+   help
+ Command DB queries shared memory by key string for shared system
+ resources. Platform drivers that require to set state of a shared
+ resource on a RPM-hardened platform must use this database to get
+ SoC specific identifier and information for the shared resources.
+
+config QCOM_RPMH
+   bool "Qualcomm RPMh support"
+   depends on QCOM_COMMAND_DB
+   help
+ Say y here to support the Qualcomm RPMh (resource peripheral manager)
+ if you need to control regulators on Qualcomm platforms, say y here.
+
+endif # SOC_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
new file mode 100644
index ..78fae8bbfa16
--- /dev/null
+++ b/drivers/soc/qcom/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_QCOM_RPMH) += rpmh-rsc.o rpmh.o
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
new file mode 100644
index ..d84572662017
--- /dev/null
+++ b/drivers/soc/qcom/cmd-db.c
@@ -0,0 +1,393 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define NUM_PRIORITY   2
+#define MAX_SLV_ID 8
+#define SLAVE_ID_MASK  0x7
+#define SLAVE_ID_SHIFT 16
+#define SLAVE_ID(addr) FIELD_GET(GENMASK(19, 16), addr)
+#define VRM_ADDR(addr) FIELD_GET(GENMASK(19, 4), addr)
+
+/**
+ * struct entry_header: header for each entry in cmddb
+ *
+ * @id: resource's identifier
+ * @priority: unused
+ * @addr: the address of the resource
+ * @len: length of the data
+ * @offset: offset from :@data_offset, start of the data
+ */
+struct entry_header {
+   u8 id[8];
+   __le32 priority[NUM_PRIORITY];
+   __le32 addr;
+   __le16 len;
+   __le16 offset;
+};
+
+/**
+ * struct rsc_hdr: resource header information
+ *
+ * @slv_id: id for the resource
+ * @header_offset: entry's header at offset from the end of the cmd_db_header
+ * @data_offset: entry's data at offset from the end of the cmd_db_header
+ * @cnt: number of entries for HW type
+ * @version: MSB is major, LSB is minor
+ * @reserved: reserved for future use.
+ */
+struct rsc_hdr {
+   __le16 slv_id;
+   __le16 header_offset;
+   __le16 data_offset;
+   __le16 cnt;
+   __le16 version;
+   __le16 reserved[3];
+};
+
+/**
+ * struct cmd_db_header: The DB header information
+ *
+ * @version: The cmd db version
+ * @magic: constant expected in the database
+ * @header: a

[PATCH v4 03/21] soc: qcom: cmd-db: adjust headers for U-Boot

2024-07-09 Thread Caleb Connolly
Replace unused/unsupported Linux headers with appropriate U-Boot
alternatives.

Signed-off-by: Caleb Connolly 
---
 drivers/soc/qcom/cmd-db.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index d84572662017..685b6d530136 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -3,18 +3,16 @@
  * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
  * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
  */
 
-#include 
-#include 
+#define pr_fmt(fmt) "cmd-db: " fmt
+
+#include 
+#include 
 #include 
-#include 
-#include 
-#include 
-#include 
-#include 
-#include 
 #include 
+#include 
+#include 
 
 #include 
 
 #define NUM_PRIORITY   2

-- 
2.45.2



[PATCH v4 01/21] linux/bitmap.h: add bitmap_empty helper

2024-07-09 Thread Caleb Connolly
Import this function from Linux as of 6.10-rc6

Signed-off-by: Caleb Connolly 
---
 include/linux/bitmap.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h
index 0a8503af9f14..40ca2212cb40 100644
--- a/include/linux/bitmap.h
+++ b/include/linux/bitmap.h
@@ -195,8 +195,16 @@ static inline void bitmap_fill(unsigned long *dst, 
unsigned int nbits)
memset(dst, 0xff, len);
}
 }
 
+static inline bool bitmap_empty(const unsigned long *src, unsigned int nbits)
+{
+   if (small_const_nbits(nbits))
+   return !(*src & BITMAP_LAST_WORD_MASK(nbits));
+
+   return find_first_bit(src, nbits) == nbits;
+}
+
 static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
 const unsigned long *src2, unsigned int nbits)
 {
if (small_const_nbits(nbits))

-- 
2.45.2



[PATCH v4 00/21] qcom: rpmh core and regulator support

2024-07-09 Thread Caleb Connolly
This series introduces support for the RPMh (Resource Power Manager
(hardened)) co-processor and associated regulator driver found on most
modern Qualcomm platforms (since ~2017).

Even though most regulators are controlled via SPMI, the specific
regions on the PMICs for controlling the regulators are restricted and
can't be accessed by the Applications Processor (AP/HLOS). Instead,
these resources are proxied via the RPMh where they can be voted on by
multiple subsystems (Linux, the modem, and the other DSPs). This is done
for security (to protect clocks, power domains, and regulators that are
specifically relevant for the trustzone) as well as to simplify the
management of shared peripherals and to allow for handover of
peripherals like the USB controller.

For U-Boot, our main concern is the regulators. Since all regulators on
the system are controlled via the RPMh, it is necessary to support it to
enable USB VBUS on some platforms, and may be needed for other
peripherals in the future.

Communicating with the RPMh additional requires accessing the cmd-db
shared memory region, this contains key/value maps to determine the
address of specific resources on the RPMh.

Introduce support for the cmd-db, the RPMh framework, and some of the
regulators that are necessary to enable USB VBUS on the RB5 development
board.

These drivers are taken from Linux, then modified and simplified for
U-Boot. The original Linux drivers contain heavy optimisations related
to multithreading and asynchronous probing, as well as support for idle
and suspend states which we don't need to deal with here. This unused
code is removed before finally adjusting the drivers to properly build
for U-Boot and use its device model.

The U-Boot version of the driver supports a single ACTIVE_ONLY TCS and
waits for it to be cleared after use. We don't support programming
low power states.

---
Changes in v4:
- Denote original Linux version in bitmap.h patch
- Rebased on Linux 6.10-rc6 and re-apply U-Boot changes preserving git
  history. Allowing for future changes to the Linux drivers to be ported
  over more easily.
- Add missing check to wait for the TCS to be cleared after use (seems
  we were just racing the RPMh before, oops!).
- Fix missing n_modes in pmic5_pldo regulator.
- Link to v3: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v3-0-846cc6c5b...@linaro.org

Changes in v3:
- Don't call dm_scan_fdt_dev(), since DM core will scan.
- Link to v2: 
https://lore.kernel.org/r/20240708-b4-qcom-rpmh-v2-0-8bc765606...@linaro.org

Changes in v2:
- Implement Neil's suggestions and fixes for SM8[56]50
- Slightly refactor cmd_db_init() for better abstraction.
- Improve logging (printf -> log_err/dev_err)
- Add missing error check in rpmh_regulators_bind()
- Link to v1: 
https://lore.kernel.org/r/20240617-b4-qcom-rpmh-v1-0-bd2336923...@linaro.org

---
Caleb Connolly (21):
  linux/bitmap.h: add bitmap_empty helper
  soc: qcom: import rpmh and cmd-db drivers from Linux
  soc: qcom: cmd-db: adjust headers for U-Boot
  soc: qcom: cmd-db: drop unused functions
  soc: qcom: cmd-db: replace cmd_db_ready() with cmd_db_init()
  soc: qcom: cmd-db: adjust for U-Boot API
  soc: qcom: rpmh-rsc: drop unused multi-threading and non-active TCS 
support
  soc: qcom: rpmh-rsc: adjust headers for U-Boot
  soc: qcom: rpmh-rsc: adjust probe for U-Boot
  soc: qcom: rpmh-rsc: remaining U-Boot API changes
  soc: qcom: rpmh: adjust headers for U-Boot
  soc: qcom: rpmh: drop unused functions
  soc: qcom: rpmh: U-Boot API changes
  power: regulator: import qcom-rpmh-regulator from Linux
  power: regulator: adjust headers for U-Boot
  power: regulator: qcom-rpmh-regulator: port over lineage_range helpers
  power: regulator: adjust structs for U-Boot
  power: regulator: qcom-rpmh-regulator: remove unused regulators
  power: regulator: qcom-rpmh-regulator: port ops to U-Boot
  power: regulator: qcom-rpmh-regulator: adjust probe for U-Boot
  qcom_defconfig: enable rpmh regulators

 configs/qcom_defconfig|   5 +
 drivers/power/regulator/Kconfig   |   8 +
 drivers/power/regulator/Makefile  |   1 +
 drivers/power/regulator/qcom-rpmh-regulator.c | 544 ++
 drivers/soc/Kconfig   |   1 +
 drivers/soc/Makefile  |   1 +
 drivers/soc/qcom/Kconfig  |  27 ++
 drivers/soc/qcom/Makefile |   4 +
 drivers/soc/qcom/cmd-db.c | 213 ++
 drivers/soc/qcom/rpmh-internal.h  | 138 +++
 drivers/soc/qcom/rpmh-rsc.c   | 518 
 drivers/soc/qcom/rpmh.c   | 110 ++
 include/linux/bitmap.h|   8 +
 include/soc/qcom/cmd-db.h |  33 ++
 include/soc/qcom/rpmh.h   |  28 ++
 include/soc/qcom/tc

[PATCH v3 5/5] fixup! soc: qcom: rpmh and cmd-db drivers

2024-07-08 Thread Caleb Connolly
---
 drivers/soc/qcom/rpmh-rsc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c
index 1f8428c415a1..30756a32d590 100644
--- a/drivers/soc/qcom/rpmh-rsc.c
+++ b/drivers/soc/qcom/rpmh-rsc.c
@@ -549,9 +549,9 @@ static int rpmh_rsc_bind(struct udevice *dev)
ret = cmd_db_init();
if (ret)
return ret;
 
-   return dm_scan_fdt_dev(dev);
+   return 0;
 }
 
 static int rpmh_rsc_probe(struct udevice *dev)
 {

-- 
2.45.2



[PATCH v3 2/5] soc: qcom: rpmh and cmd-db drivers

2024-07-08 Thread Caleb Connolly
Introduce two Qualcomm SoC drivers, the RPMh and cmd-db. RPMh is a the
name for the second generation Resource Power Management hub on Qualcomm
SoCs. Most core regulators have to be controlled via this hub.

The cmd-db is a region of memory which contains offsets and data about
how to communicate with the RPMh.

Tested-by: Neil Armstrong  # on SM8550 & SM8^%)
Signed-off-by: Caleb Connolly 
---
 drivers/soc/Kconfig  |   1 +
 drivers/soc/Makefile |   1 +
 drivers/soc/qcom/Kconfig |  25 ++
 drivers/soc/qcom/Makefile|   4 +
 drivers/soc/qcom/cmd-db.c| 261 
 drivers/soc/qcom/rpmh-internal.h | 141 +
 drivers/soc/qcom/rpmh-rsc.c  | 628 +++
 drivers/soc/qcom/rpmh.c  | 112 +++
 include/soc/qcom/cmd-db.h|  42 +++
 include/soc/qcom/rpmh.h  |  29 ++
 include/soc/qcom/tcs.h   |  78 +
 11 files changed, 1322 insertions(+)

diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index cee506fe4747..8ef408d9ba1b 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -47,8 +47,9 @@ config SOC_XILINX_VERSAL_NET
  Enable this option to select SoC device id driver for Xilinx Versal 
NET.
  This allows other drivers to verify the SoC familiy & revision using
  matching SoC attributes.
 
+source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/samsung/Kconfig"
 source "drivers/soc/ti/Kconfig"
 
 endmenu
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 5ec89a053165..abcc8a88950f 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -4,8 +4,9 @@
 
 obj-$(CONFIG_SOC_AMD_VERSAL2) += soc_amd_versal2.o
 obj-$(CONFIG_SOC_SAMSUNG) += samsung/
 obj-$(CONFIG_SOC_TI) += ti/
+obj-$(CONFIG_SOC_QCOM) += qcom/
 obj-$(CONFIG_SOC_DEVICE) += soc-uclass.o
 obj-$(CONFIG_SOC_DEVICE_TI_K3) += soc_ti_k3.o
 obj-$(CONFIG_SANDBOX) += soc_sandbox.o
 obj-$(CONFIG_SOC_XILINX_ZYNQMP) += soc_xilinx_zynqmp.o
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
new file mode 100644
index ..a0872c5b3c83
--- /dev/null
+++ b/drivers/soc/qcom/Kconfig
@@ -0,0 +1,25 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+menuconfig SOC_QCOM
+   bool "Qualcomm SOC drivers support"
+   help
+ Say Y here if you want to enable Qualcomm SOC drivers support.
+
+if SOC_QCOM
+
+config QCOM_COMMAND_DB
+   bool "Qualcomm Command DB"
+   help
+ Command DB queries shared memory by key string for shared system
+ resources. Platform drivers that require to set state of a shared
+ resource on a RPM-hardened platform must use this database to get
+ SoC specific identifier and information for the shared resources.
+
+config QCOM_RPMH
+   bool "Qualcomm RPMh support"
+   depends on QCOM_COMMAND_DB
+   help
+ Say y here to support the Qualcomm RPMh (resource peripheral manager)
+ if you need to control regulators on Qualcomm platforms, say y here.
+
+endif # SOC_QCOM
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
new file mode 100644
index ..4fca569cfb77
--- /dev/null
+++ b/drivers/soc/qcom/Makefile
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
+obj-$(CONFIG_QCOM_RPMH)+= rpmh-rsc.o rpmh.o
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
new file mode 100644
index ..62f1479bda09
--- /dev/null
+++ b/drivers/soc/qcom/cmd-db.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2016-2018, 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023, Linaro Ltd.
+ */
+
+#define pr_fmt(fmt) "cmd-db: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define NUM_PRIORITY   2
+#define MAX_SLV_ID 8
+#define SLAVE_ID_MASK  0x7
+#define SLAVE_ID_SHIFT 16
+
+/**
+ * struct entry_header: header for each entry in cmddb
+ *
+ * @id: resource's identifier
+ * @priority: unused
+ * @addr: the address of the resource
+ * @len: length of the data
+ * @offset: offset from :@data_offset, start of the data
+ */
+struct entry_header {
+   u8 id[8];
+   __le32 priority[NUM_PRIORITY];
+   __le32 addr;
+   __le16 len;
+   __le16 offset;
+};
+
+/**
+ * struct rsc_hdr: resource header information
+ *
+ * @slv_id: id for the resource
+ * @header_offset: entry's header at offset from the end of the cmd_db_header
+ * @data_offset: entry's data at offset from the end of the cmd_db_header
+ * @cnt: number of entries for HW type
+ * @version: MSB is major, LSB is minor
+ * @reserved: reserved for future use.
+ */
+struct rsc_hdr {
+   __le16 slv_id;
+   __le16 header_offset;
+   __le16 data_offset;
+   __le16 cnt;
+   __le16 version;
+   __le16 reserved[3];
+

  1   2   3   4   5   6   7   8   9   10   >