diff options
| author | Anup Patel <[email protected]> | 2023-07-21 13:39:50 +0530 |
|---|---|---|
| committer | Anup Patel <[email protected]> | 2023-07-31 14:09:08 +0530 |
| commit | 14a35b0e0e8ceaeb664c5078d6a1fec9e7193c72 (patch) | |
| tree | 10bdf4f4ff93db305a17746d43618dd6d7234532 /lib/utils | |
| parent | 44c5151293849736118090bf5230d6b298a9d0b0 (diff) | |
lib: utils/regmap: Add generic regmap access library
We add generic regmap access library which is independent of
hardware description format (FDT or ACPI). The OpenSBI platform
support or regmap drivers can register regmap instances which
can be discovered by different regmap clients based on the
unique ID of regmap instances.
Signed-off-by: Anup Patel <[email protected]>
Reviewed-by: Xiang W <[email protected]>
Diffstat (limited to 'lib/utils')
| -rw-r--r-- | lib/utils/Kconfig | 2 | ||||
| -rw-r--r-- | lib/utils/regmap/Kconfig | 9 | ||||
| -rw-r--r-- | lib/utils/regmap/objects.mk | 10 | ||||
| -rw-r--r-- | lib/utils/regmap/regmap.c | 114 |
4 files changed, 135 insertions, 0 deletions
diff --git a/lib/utils/Kconfig b/lib/utils/Kconfig index 5a71e750..de8b4eb9 100644 --- a/lib/utils/Kconfig +++ b/lib/utils/Kconfig @@ -14,6 +14,8 @@ source "$(OPENSBI_SRC_DIR)/lib/utils/irqchip/Kconfig" source "$(OPENSBI_SRC_DIR)/lib/utils/libfdt/Kconfig" +source "$(OPENSBI_SRC_DIR)/lib/utils/regmap/Kconfig" + source "$(OPENSBI_SRC_DIR)/lib/utils/reset/Kconfig" source "$(OPENSBI_SRC_DIR)/lib/utils/serial/Kconfig" diff --git a/lib/utils/regmap/Kconfig b/lib/utils/regmap/Kconfig new file mode 100644 index 00000000..8db5c8b8 --- /dev/null +++ b/lib/utils/regmap/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: BSD-2-Clause + +menu "Regmap Support" + +config REGMAP + bool "Regmap support" + default n + +endmenu diff --git a/lib/utils/regmap/objects.mk b/lib/utils/regmap/objects.mk new file mode 100644 index 00000000..5d1bead0 --- /dev/null +++ b/lib/utils/regmap/objects.mk @@ -0,0 +1,10 @@ +# +# SPDX-License-Identifier: BSD-2-Clause +# +# Copyright (c) 2023 Ventana Micro Systems Inc. +# +# Authors: +# Anup Patel <[email protected]> +# + +libsbiutils-objs-$(CONFIG_REGMAP) += regmap/regmap.o diff --git a/lib/utils/regmap/regmap.c b/lib/utils/regmap/regmap.c new file mode 100644 index 00000000..a2180c88 --- /dev/null +++ b/lib/utils/regmap/regmap.c @@ -0,0 +1,114 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + * Authors: + * Anup Patel <[email protected]> + */ + +#include <sbi/sbi_error.h> +#include <sbi_utils/regmap/regmap.h> + +static SBI_LIST_HEAD(regmap_list); + +struct regmap *regmap_find(unsigned int id) +{ + struct sbi_dlist *pos; + + sbi_list_for_each(pos, &(regmap_list)) { + struct regmap *rmap = to_regmap(pos); + + if (rmap->id == id) + return rmap; + } + + return NULL; +} + +int regmap_add(struct regmap *rmap) +{ + if (!rmap) + return SBI_EINVAL; + if (regmap_find(rmap->id)) + return SBI_EALREADY; + + sbi_list_add(&(rmap->node), &(regmap_list)); + + return 0; +} + +void regmap_remove(struct regmap *rmap) +{ + if (!rmap) + return; + + sbi_list_del(&(rmap->node)); +} + +static bool regmap_reg_valid(struct regmap *rmap, unsigned int reg) +{ + if ((reg >= rmap->reg_max) || + (reg & (rmap->reg_stride - 1))) + return false; + return true; +} + +static unsigned int regmap_reg_addr(struct regmap *rmap, unsigned int reg) +{ + reg += rmap->reg_base; + + if (rmap->reg_shift > 0) + reg >>= rmap->reg_shift; + else if (rmap->reg_shift < 0) + reg <<= -(rmap->reg_shift); + + return reg; +} + +int regmap_read(struct regmap *rmap, unsigned int reg, unsigned int *val) +{ + if (!rmap || !regmap_reg_valid(rmap, reg)) + return SBI_EINVAL; + if (!rmap->reg_read) + return SBI_ENOSYS; + + return rmap->reg_read(rmap, regmap_reg_addr(rmap, reg), val); +} + +int regmap_write(struct regmap *rmap, unsigned int reg, unsigned int val) +{ + if (!rmap || !regmap_reg_valid(rmap, reg)) + return SBI_EINVAL; + if (!rmap->reg_write) + return SBI_ENOSYS; + + return rmap->reg_write(rmap, regmap_reg_addr(rmap, reg), val); +} + +int regmap_update_bits(struct regmap *rmap, unsigned int reg, + unsigned int mask, unsigned int val) +{ + int rc; + unsigned int reg_val; + + if (!rmap || !regmap_reg_valid(rmap, reg)) + return SBI_EINVAL; + + if (rmap->reg_update_bits) { + return rmap->reg_update_bits(rmap, regmap_reg_addr(rmap, reg), + mask, val); + } else if (rmap->reg_read && rmap->reg_write) { + reg = regmap_reg_addr(rmap, reg); + + rc = rmap->reg_read(rmap, reg, ®_val); + if (rc) + return rc; + + reg_val &= ~mask; + reg_val |= val & mask; + return rmap->reg_write(rmap, reg, reg_val); + } + + return SBI_ENOSYS; +} |
