summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig7
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/imx_ele/ele_api.c32
-rw-r--r--drivers/misc/rockchip-io-domain.c79
-rw-r--r--drivers/misc/socfpga_dtreg.c115
5 files changed, 230 insertions, 4 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index f11ce72525f..98043fc2ff3 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -689,4 +689,11 @@ config SL28CPLD
the base driver which provides common access methods for the
sub-drivers.
+config SPL_SOCFPGA_DT_REG
+ bool "Enable register setting from device tree in SPL"
+ depends on SPL
+ help
+ Enable register setting from device tree. This also
+ provides user a clean interface and all register settings are
+ centralized in one place, device tree.
endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 0432db6ed12..1522f6c3b7d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -90,3 +90,4 @@ obj-$(CONFIG_K3_AVS0) += k3_avs.o
obj-$(CONFIG_ESM_K3) += k3_esm.o
obj-$(CONFIG_ESM_PMIC) += esm_pmic.o
obj-$(CONFIG_SL28CPLD) += sl28cpld.o
+obj-$(CONFIG_SPL_SOCFPGA_SEC_REG) += socfpga_dtreg.o
diff --git a/drivers/misc/imx_ele/ele_api.c b/drivers/misc/imx_ele/ele_api.c
index 0c017734a49..e0ec22c7abf 100644
--- a/drivers/misc/imx_ele/ele_api.c
+++ b/drivers/misc/imx_ele/ele_api.c
@@ -528,6 +528,38 @@ int ele_start_rng(void)
return ret;
}
+int ele_commit(u16 fuse_id, u32 *response, u32 *info_type)
+{
+ struct udevice *dev = gd->arch.ele_dev;
+ int size = sizeof(struct ele_msg);
+ struct ele_msg msg;
+ int ret = 0;
+
+ if (!dev) {
+ printf("ele dev is not initialized\n");
+ return -ENODEV;
+ }
+
+ msg.version = ELE_VERSION;
+ msg.tag = ELE_CMD_TAG;
+ msg.size = 2;
+ msg.command = ELE_COMMIT_REQ;
+ msg.data[0] = fuse_id;
+
+ ret = misc_call(dev, false, &msg, size, &msg, size);
+ if (ret)
+ printf("Error: %s: ret %d, fuse_id 0x%x, response 0x%x\n",
+ __func__, ret, fuse_id, msg.data[0]);
+
+ if (response)
+ *response = msg.data[0];
+
+ if (info_type)
+ *info_type = msg.data[1];
+
+ return ret;
+}
+
int ele_write_secure_fuse(ulong signed_msg_blk, u32 *response)
{
struct udevice *dev = gd->arch.ele_dev;
diff --git a/drivers/misc/rockchip-io-domain.c b/drivers/misc/rockchip-io-domain.c
index 3f6227f993f..0ffea32ef07 100644
--- a/drivers/misc/rockchip-io-domain.c
+++ b/drivers/misc/rockchip-io-domain.c
@@ -5,7 +5,6 @@
* Ported from linux drivers/soc/rockchip/io-domain.c
*/
-#include <common.h>
#include <dm.h>
#include <dm/device_compat.h>
#include <regmap.h>
@@ -28,6 +27,10 @@
#define MAX_VOLTAGE_1_8 1980000
#define MAX_VOLTAGE_3_3 3600000
+#define RK3399_PMUGRF_CON0 0x180
+#define RK3399_PMUGRF_CON0_VSEL BIT(8)
+#define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9
+
#define RK3568_PMU_GRF_IO_VSEL0 0x0140
#define RK3568_PMU_GRF_IO_VSEL1 0x0144
#define RK3568_PMU_GRF_IO_VSEL2 0x0148
@@ -35,10 +38,10 @@
struct rockchip_iodomain_soc_data {
int grf_offset;
const char *supply_names[MAX_SUPPLIES];
- int (*write)(struct regmap *grf, int idx, int uV);
+ int (*write)(struct regmap *grf, uint offset, int idx, int uV);
};
-static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV)
+static int rk3568_iodomain_write(struct regmap *grf, uint offset, int idx, int uV)
{
u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
u32 val0, val1;
@@ -78,6 +81,64 @@ static int rk3568_iodomain_write(struct regmap *grf, int idx, int uV)
return 0;
}
+static int rockchip_iodomain_write(struct regmap *grf, uint offset, int idx, int uV)
+{
+ u32 val;
+
+ /* set value bit */
+ val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
+ val <<= idx;
+
+ /* apply hiword-mask */
+ val |= (BIT(idx) << 16);
+
+ return regmap_write(grf, offset, val);
+}
+
+static int rk3399_pmu_iodomain_write(struct regmap *grf, uint offset, int idx, int uV)
+{
+ int ret = rockchip_iodomain_write(grf, offset, idx, uV);
+
+ if (!ret && idx == RK3399_PMUGRF_VSEL_SUPPLY_NUM) {
+ /*
+ * set pmu io iodomain to also use this framework
+ * instead of a special gpio.
+ */
+ u32 val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
+ ret = regmap_write(grf, RK3399_PMUGRF_CON0, val);
+ }
+
+ return ret;
+}
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
+ .grf_offset = 0xe640,
+ .supply_names = {
+ "bt656-supply", /* APIO2_VDD */
+ "audio-supply", /* APIO5_VDD */
+ "sdmmc-supply", /* SDMMC0_VDD */
+ "gpio1830-supply", /* APIO4_VDD */
+ },
+ .write = rockchip_iodomain_write,
+};
+
+static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
+ .grf_offset = 0x180,
+ .supply_names = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "pmu1830-supply", /* PMUIO2_VDD */
+ },
+ .write = rk3399_pmu_iodomain_write,
+};
+
static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
.grf_offset = 0x140,
.supply_names = {
@@ -96,6 +157,14 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
static const struct udevice_id rockchip_iodomain_ids[] = {
{
+ .compatible = "rockchip,rk3399-io-voltage-domain",
+ .data = (ulong)&soc_data_rk3399,
+ },
+ {
+ .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
+ .data = (ulong)&soc_data_rk3399_pmu,
+ },
+ {
.compatible = "rockchip,rk3568-pmu-io-voltage-domain",
.data = (ulong)&soc_data_rk3568_pmu,
},
@@ -152,7 +221,9 @@ static int rockchip_iodomain_probe(struct udevice *dev)
continue;
}
- soc_data->write(grf, i, uV);
+ ret = soc_data->write(grf, soc_data->grf_offset, i, uV);
+ if (ret)
+ dev_err(dev, "%s: Couldn't write to GRF\n", supply_name);
}
return 0;
diff --git a/drivers/misc/socfpga_dtreg.c b/drivers/misc/socfpga_dtreg.c
new file mode 100644
index 00000000000..ea5d0bcdf51
--- /dev/null
+++ b/drivers/misc/socfpga_dtreg.c
@@ -0,0 +1,115 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2024 Intel Corporation <www.intel.com>
+ */
+
+#include <dm.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <linux/sizes.h>
+
+#define NUMBER_OF_ELEMENTS 3
+
+static int socfpga_dtreg_probe(struct udevice *dev)
+{
+ const fdt32_t *list;
+ fdt_addr_t offset, base;
+ fdt_val_t val, read_val, mask, set_mask;
+ int size, i;
+ u32 blk_sz, reg;
+ ofnode node;
+ const char *name = NULL;
+
+ debug("%s(dev=%p)\n", __func__, dev);
+
+ if (!dev_has_ofnode(dev))
+ return 0;
+
+ dev_for_each_subnode(node, dev) {
+ name = ofnode_get_name(node);
+ if (!name)
+ return -EINVAL;
+
+ if (ofnode_read_u32_index(node, "reg", 1, &blk_sz))
+ return -EINVAL;
+
+ base = ofnode_get_addr(node);
+ if (base == FDT_ADDR_T_NONE)
+ return -EINVAL;
+
+ debug("%s(node_offset 0x%lx node_name %s ", __func__,
+ node.of_offset, name);
+ debug("node addr 0x%llx blk sz 0x%x)\n", base, blk_sz);
+
+ list = ofnode_read_prop(node, "intel,offset-settings", &size);
+ if (!list)
+ return -EINVAL;
+
+ debug("%s(intel,offset-settings property size=%x)\n", __func__,
+ size);
+ size /= sizeof(*list) * NUMBER_OF_ELEMENTS;
+
+ /*
+ * First element: offset
+ * Second element: val
+ * Third element: mask
+ */
+ for (i = 0; i < size; i++) {
+ offset = fdt32_to_cpu(*list++);
+ val = fdt32_to_cpu(*list++);
+
+ /* Reads the masking bit value from the list */
+ mask = fdt32_to_cpu(*list++);
+
+ /*
+ * Reads out the offsets, value and masking bits
+ * Ex: <0x00000000 0x00000230 0xffffffff>
+ */
+ debug("%s(intel,offset-settings 0x%llx : 0x%llx : 0x%llx)\n",
+ __func__, offset, val, mask);
+
+ if (blk_sz < offset + SZ_4) {
+ printf("%s: Overflow as offset 0x%llx or reg",
+ __func__, offset);
+ printf(" write is more than block size 0x%x\n",
+ blk_sz);
+ return -EINVAL;
+ }
+
+ if (mask != 0) {
+ if (mask == 0xffffffff) {
+ reg = base + offset;
+ writel(val, (uintptr_t)reg);
+ } else {
+ /* Mask the value with the masking bits */
+ set_mask = val & mask;
+
+ reg = base + offset;
+
+ /* Clears and sets specific bits in the register */
+ clrsetbits_le32((uintptr_t)reg, mask, set_mask);
+ }
+ }
+
+ read_val = readl((uintptr_t)reg);
+
+ /* Reads out the register, masked value and the read value */
+ debug("%s(reg 0x%x = wr : 0x%llx rd : 0x%llx)\n",
+ __func__, reg, set_mask, read_val);
+ }
+ }
+
+ return 0;
+};
+
+static const struct udevice_id socfpga_dtreg_ids[] = {
+ {.compatible = "intel,socfpga-dtreg"},
+ { }
+};
+
+U_BOOT_DRIVER(socfpga_dtreg) = {
+ .name = "socfpga-dtreg",
+ .id = UCLASS_NOP,
+ .of_match = socfpga_dtreg_ids,
+ .probe = socfpga_dtreg_probe,
+};