/* * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2023 Ventana Micro Systems Inc. * * Authors: * Anup Patel */ #include #include 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; }