diff --git a/Documentation/firmware-guide/acpi/dsd/soc/general.rst b/Documentation/firmware-guide/acpi/dsd/soc/general.rst
new file mode 100644
index 000000000..9c287e838
--- /dev/null
+++ b/Documentation/firmware-guide/acpi/dsd/soc/general.rst
@@ -0,0 +1,32 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========================================
+System-on-Chip (SoC) facility descriptions
+==========================================
+
+These documents describe how to create ACPI profiles for devices composed into
+system-on-chip (SoC) architectures. Currently, we only describe the options
+availed in the _DSD block for select platforms; other considerations are not
+yet applied. The inspiration for these documents are based around the advent
+(as of March 2024) of hefty, non-Apple ARM SoC systems such as the Rockchip
+RK3588 and newer chips that have desktop-like performance and thus are prime
+candidates for a UEFI-based desktop-like boot system with the goal being to
+deliver the same user-friendly ease of loading operating systems as on the
+Intel x86 sphere. Open-source UEFI-based firmware engines, such as TianoCore
+[1], mean it is possible on such platforms for the open-source developer to
+control both firmware and kernel simultaneously, which is not the case for
+the situation with Intel-based PC boards where boards are provided with pre-
+baked, vendor-selected and opaque firmwares.
+
+The description of ACPI usage here is not meant to suggest that ACPI replace
+Device Tree altogether for such SoCs; rather, we recognize that given they
+often will have a variety of applications that may include embedded usage where
+that more hard-wired boot loader setups such as U-Boot still shine, the
+maintenance of ACPI and DTB-based configuration options should be in parallel,
+and it may be possible for the same firmware to deploy both options.
+
+References
+==========
+
+[1] EDK2-RK3588 port of TianoCore EDK2 firmware.
+    https://github.com/edk2-porting/edk2-rk3588
diff --git a/Documentation/firmware-guide/acpi/dsd/soc/soc-i2c.rst b/Documentation/firmware-guide/acpi/dsd/soc/soc-i2c.rst
new file mode 100644
index 000000000..0e6c5df65
--- /dev/null
+++ b/Documentation/firmware-guide/acpi/dsd/soc/soc-i2c.rst
@@ -0,0 +1,59 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+I2C buses on SoCs
+=================
+
+This document describes the ACPI _DSD parameters currently being employed for
+Inter-Integrated Circuit (I2C) buses in the Linux kernel. It is based off the
+conventions used in the Rockchip RK3588 firmware project [1], which is also the
+first SoC documented here.
+
+General considerations
+======================
+
+For general use, we recommend indicating I2C busses in the ACPI firmware table
+in the following manner. First, they should be named I2Cx, where "x" is the bus
+index, and that index should also be used for the _UID component, e.g. on
+Rockchip RK3588 (see below), we use:
+
+  Device (I2Cx) {
+    Name (_HID, "RKCP3001")
+    Name (_CID, "PRP0001")
+    Name (_UID, x)
+    Name (_CCA, 0)
+
+    ...
+  }
+
+Interrupts should be specified in the usual ACPI manner. Likewise, as of ACPI
+6.5, clock rates should be given in ClockInput resources. Parameters specific to
+the Rockchip and I2C devices are indicated in the _DSD block as given below.
+The parameters are a curated selection from the Device Tree Blob (DTB)
+representation.
+
+_DSD parameters for different SoCs
+==================================
+
+Rockchip RK3588
+---------------
+
+The following parameters are indicated here for the I2C on Rockchip RK3588.
+
+- i2c,clk-rate 	Describe the pclk rate for the I2C bus, in Hz.
+- rockchip,bclk	Describe the bclk rate for the I2C bus, in Hz.
+
+These two parameters describe the peripheral (pclk) and bus (bclk) clock rates
+for the I2C bus. It is NOT recommended to use these clock rate parameters in the
+kernel, as they are intended for compatibility with Microsoft Windows. They are
+ONLY mentioned here for documentation's sake. Instead, the method mentioned
+earlier should be used to provide the clock rates; in the current revisions of
+the i2c-rk3x driver, the first clock resource appearing (resource 0) will be
+treated as giving the bclk rate, and the second clock resource (resource 1)
+appearing will be treated as giving the pclk rate.
+
+References
+==========
+
+[1] EDK2-RK3588 port of TianoCore EDK2 firmware.
+    https://github.com/edk2-porting/edk2-rk3588
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 8cc8c0d9c..26343ffce 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -48,6 +48,7 @@ acpi-$(CONFIG_PCI)		+= pci_root.o pci_link.o pci_irq.o
 obj-$(CONFIG_ACPI_MCFG)		+= pci_mcfg.o
 acpi-$(CONFIG_PCI)		+= acpi_lpss.o
 acpi-y				+= acpi_apd.o
+acpi-y				+= acpi_clk.o
 acpi-y				+= acpi_platform.o
 acpi-y				+= acpi_pnp.o
 acpi-y				+= power.o
diff --git a/drivers/acpi/acpi_clk.c b/drivers/acpi/acpi_clk.c
new file mode 100644
index 000000000..fbb1c4a4a
--- /dev/null
+++ b/drivers/acpi/acpi_clk.c
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * drivers/acpi/acpi_clk.c - ACPI device clock resources support.
+ *
+ * (C) 2023 Niyas Sait <niyas.sait@huawei.com>
+ * (C) 2024 Shimrra Shai <shimmyshai00@gmail.com>
+ *
+ */
+
+#include <linux/acpi.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+struct acpi_clk_lookup {
+	u16 freq_div;
+	u32 freq_num;
+	u8 scale;
+	u8 mode;
+	int index;
+	bool found;
+	int n;
+};
+
+static uint64_t calc_clock_rate(u32 freq_num, u16 freq_denom, u8 scale)
+{
+	uint32_t scale_factor[3] = { 1, 1000, 1000000 };
+	uint64_t rate = 0;
+
+	if (scale < ARRAY_SIZE(scale_factor))
+		rate = DIV_ROUND_UP(freq_num * scale_factor[scale], freq_denom);
+
+	return rate;
+}
+
+static int acpi_populate_clk_lookup(struct acpi_resource *ares, void *data)
+{
+	struct acpi_clk_lookup *lookup = data;
+	struct acpi_resource_clock_input *resource = &ares->data.clock_input;
+
+	if (ares->type != ACPI_RESOURCE_TYPE_CLOCK_INPUT)
+		return 1;
+
+	if (lookup->n++ != lookup->index)
+		return 1;
+
+	lookup->mode = resource->mode;
+	lookup->freq_div = resource->frequency_divisor;
+	lookup->freq_num = resource->frequency_numerator;
+	lookup->scale = resource->scale;
+	lookup->found = true;
+
+	return 1;
+}
+
+struct clk *acpi_clk_register(struct acpi_device *adev, int index,
+			      const char *name)
+{
+	struct acpi_clk_lookup lookup;
+	struct list_head list;
+	struct clk *clk;
+	uint64_t rate;
+	int ret;
+
+	INIT_LIST_HEAD(&list);
+
+	memset(&lookup, 0, sizeof(lookup));
+	lookup.index = index;
+
+	ret = acpi_dev_get_resources(adev, &list, acpi_populate_clk_lookup,
+				     &lookup);
+	if (ret < 0)
+		return ERR_PTR(-ENODEV);
+
+	acpi_dev_free_resource_list(&list);
+
+	/* register fixed clocks only */
+	if (!lookup.found || lookup.mode != 0)
+		return ERR_PTR(-EINVAL);
+
+	rate = calc_clock_rate(lookup.freq_num, lookup.freq_div, lookup.scale);
+
+	const char *regname = name;
+
+	if (name == NULL)
+		regname = dev_name(&adev->dev);
+
+	clk = clk_register_fixed_rate(&adev->dev, regname, NULL, 0, rate);
+	clk_register_clkdev(clk, regname, NULL);
+
+	return clk;
+}
+EXPORT_SYMBOL_GPL(acpi_clk_register);
+
diff --git a/drivers/i2c/busses/i2c-rk3x.c b/drivers/i2c/busses/i2c-rk3x.c
index 086fdf262..1aaf2daba 100644
--- a/drivers/i2c/busses/i2c-rk3x.c
+++ b/drivers/i2c/busses/i2c-rk3x.c
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
+#include <linux/acpi.h>
 #include <linux/spinlock.h>
 #include <linux/clk.h>
 #include <linux/wait.h>
@@ -1235,6 +1236,15 @@ static const struct of_device_id rk3x_i2c_match[] = {
 };
 MODULE_DEVICE_TABLE(of, rk3x_i2c_match);
 
+#ifdef CONFIG_ACPI
+/* for RK3588 and at least when loaded with EDK2-RK3588 Tianocore firmware */
+static const struct acpi_device_id rk3x_i2c_acpi_match[] = {
+	{ .id = "RKCP3001", .driver_data = (kernel_ulong_t)&rk3399_soc_data },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, rk3x_i2c_acpi_match);
+#endif
+
 static int rk3x_i2c_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -1243,6 +1253,8 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	int ret = 0;
 	int bus_nr;
 	u32 value;
+	u64 value64;
+	char name[64];
 	int irq;
 	unsigned long clk_rate;
 
@@ -1250,8 +1262,12 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	if (!i2c)
 		return -ENOMEM;
 
-	match = of_match_node(rk3x_i2c_match, np);
-	i2c->soc_data = match->data;
+	if (acpi_disabled) {
+		match = of_match_node(rk3x_i2c_match, np);
+		i2c->soc_data = match->data;
+	} else {
+		i2c->soc_data = device_get_match_data(&pdev->dev);
+	}
 
 	/* use common interface to get I2C timing properties */
 	i2c_parse_fw_timings(&pdev->dev, &i2c->t, true);
@@ -1266,6 +1282,9 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 	i2c->dev = &pdev->dev;
 
+	if (!acpi_disabled)
+		ACPI_COMPANION_SET(&i2c->adap.dev, ACPI_COMPANION(&pdev->dev));
+
 	spin_lock_init(&i2c->lock);
 	init_waitqueue_head(&i2c->wait);
 
@@ -1273,8 +1292,25 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 	if (IS_ERR(i2c->regs))
 		return PTR_ERR(i2c->regs);
 
-	/* Try to set the I2C adapter number from dt */
-	bus_nr = of_alias_get_id(np, "i2c");
+	if (acpi_disabled) {
+		/* Try to set the I2C adapter number from dt */
+		bus_nr = of_alias_get_id(np, "i2c");
+	} else {
+		ret = acpi_dev_uid_to_integer(ACPI_COMPANION(&pdev->dev),
+					      &value64);
+		if (ret) {
+			dev_err(&pdev->dev, "Cannot retrieve UID\n");
+			return ret;
+		}
+
+		if (value64 < INT_MAX) {
+			bus_nr = (int) value64;
+		} else {
+			/* shouldn't happen!!! */
+			dev_err(&pdev->dev, "Too big UID\n");
+			return -EINVAL;
+		}
+	}
 
 	/*
 	 * Switch to new interface if the SoC also offers the old one.
@@ -1325,13 +1361,36 @@ static int rk3x_i2c_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, i2c);
 
-	if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
-		/* Only one clock to use for bus clock and peripheral clock */
-		i2c->clk = devm_clk_get(&pdev->dev, NULL);
-		i2c->pclk = i2c->clk;
+	if (acpi_disabled) {
+		if (i2c->soc_data->calc_timings == rk3x_i2c_v0_calc_timings) {
+			/* Only one clock to use for bus clock and peripheral
+			 * clock
+			 */
+			i2c->clk = devm_clk_get(&pdev->dev, NULL);
+			i2c->pclk = i2c->clk;
+		} else {
+			i2c->clk = devm_clk_get(&pdev->dev, "i2c");
+			i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+		}
 	} else {
-		i2c->clk = devm_clk_get(&pdev->dev, "i2c");
-		i2c->pclk = devm_clk_get(&pdev->dev, "pclk");
+		if (i2c->soc_data->calc_timings != rk3x_i2c_v0_calc_timings) {
+			snprintf(name, sizeof(name), "rk3x-i2c[%d].bclk",
+				 bus_nr);
+			i2c->clk = acpi_clk_register(ACPI_COMPANION(&pdev->dev),
+						     0, name);
+
+			snprintf(name, sizeof(name), "rk3x-i2c[%d].pclk",
+				 bus_nr);
+			i2c->pclk = acpi_clk_register(ACPI_COMPANION(&pdev->dev),
+						      1, name);
+		} else {
+			/* NB: currently not expected w/UEFI firmware given
+			 * these are not super performant RK3xxx
+			 */
+			dev_err(&pdev->dev,
+				"ACPI not supported for this RK3xxx\n");
+			return -EINVAL;
+		}
 	}
 
 	if (IS_ERR(i2c->clk))
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 34829f2c5..13ca67d2c 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -32,6 +32,7 @@ struct irq_domain_ops;
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/fw_table.h>
+#include <linux/clk-provider.h>
 
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
@@ -1569,4 +1570,11 @@ static inline bool acpi_node_backed_by_real_pxm(int nid)
 }
 #endif
 
+/* Clock support */
+
+#ifdef CONFIG_ACPI
+struct clk *acpi_clk_register(struct acpi_device *adev, int index,
+			      const char *name);
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
