// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2021, The Linux Foundation. All rights reserved. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include #include #include #include #include #include #include #include #include "qbg-core.h" #include "qbg-sdam.h" int qbg_sdam_read(struct qti_qbg *chip, int offset, u8 *data, int len) { int rc; rc = regmap_bulk_read(chip->regmap, offset, data, len); if (rc < 0) pr_err("Failed to read QBG SDAM offset:%04x rc=%d\n", offset, rc); return rc; } int qbg_sdam_write(struct qti_qbg *chip, int offset, u8 *data, int len) { int rc; rc = regmap_bulk_write(chip->regmap, offset, data, len); if (rc < 0) pr_err("Failed to write QBG SDAM offset:%04x rc=%d\n", offset, rc); return rc; } int qbg_sdam_get_fifo_data(struct qti_qbg *chip, struct fifo_data *fifo, u32 fifo_count) { int rc = 0, i = 0; u32 num_sdams, fifo_data_length, bytes_read = 0, bytes_remaining; fifo_data_length = fifo_count * QBG_ONE_FIFO_LENGTH; num_sdams = fifo_data_length / QBG_SDAM_ONE_FIFO_REGION_SIZE; if (num_sdams > chip->num_data_sdams) { pr_err("Fifo count exceeds QBG SDAMs\n"); return -EINVAL; } qbg_dbg(chip, QBG_DEBUG_SDAM, "Completely filled sdams=%d\n", num_sdams); /* First read SDAMs that are completely filled */ for (i = 0; i < num_sdams; i++) { rc = qbg_sdam_read(chip, QBG_SDAM_DATA_START_OFFSET(chip, (SDAM_DATA0 + i)), (((u8 *)fifo) + bytes_read), QBG_SDAM_ONE_FIFO_REGION_SIZE); if (rc < 0) { pr_err("Failed to read QBG SDAM%d, rc=%d\n", i, rc); return rc; } bytes_read += QBG_SDAM_ONE_FIFO_REGION_SIZE; } /* Next read SDAM that is partially filled */ bytes_remaining = fifo_data_length - bytes_read; qbg_dbg(chip, QBG_DEBUG_SDAM, "Valid data in partially filled sdam:%d bytes\n", bytes_remaining); if (bytes_remaining) { rc = qbg_sdam_read(chip, QBG_SDAM_DATA_START_OFFSET(chip, (SDAM_DATA0 + i)), (((u8 *)fifo) + bytes_read), bytes_remaining); if (rc < 0) { pr_err("Failed to read remaining bytes from QBG SDAM%d, rc=%d\n", i, rc); return rc; } bytes_read += bytes_remaining; } qbg_dbg(chip, QBG_DEBUG_SDAM, "Total bytes read=%d\n", bytes_read); return rc; } int qbg_sdam_get_essential_params(struct qti_qbg *chip, u8 *params) { int rc; if (!chip || !params) return -EINVAL; rc = qbg_sdam_read(chip, chip->sdam_base + (SDAM_CTRL1 * QBG_SINGLE_SDAM_SIZE) + QBG_ESSENTIAL_PARAMS_START_OFFSET, (u8 *)params, sizeof(struct qbg_essential_params)); if (rc < 0) pr_err("Failed to read QBG essential params, rc=%d\n", rc); else qbg_dbg(chip, QBG_DEBUG_SDAM, "Read QBG essential params\n"); return rc; } int qbg_sdam_set_essential_params(struct qti_qbg *chip, u8 *params) { int rc; if (!chip || !params) return -EINVAL; rc = qbg_sdam_write(chip, chip->sdam_base + (SDAM_CTRL1 * QBG_SINGLE_SDAM_SIZE) + QBG_ESSENTIAL_PARAMS_START_OFFSET, (u8 *)params, sizeof(struct qbg_essential_params)); if (rc < 0) pr_err("Failed to write QBG essential params, rc=%d\n", rc); else qbg_dbg(chip, QBG_DEBUG_SDAM, "Written QBG essential params\n"); return rc; } int qbg_sdam_get_essential_param_revid(struct qti_qbg *chip, u8 *revid) { int rc; if (!chip || !revid) return -EINVAL; rc = qbg_sdam_read(chip, chip->sdam_base + (SDAM_CTRL1 * QBG_SINGLE_SDAM_SIZE) + QBG_ESSENTIAL_PARAMS_REVID_OFFSET, revid, 1); if (rc < 0) pr_err("Failed to read QBG essential params revid, rc=%d\n", rc); else qbg_dbg(chip, QBG_DEBUG_SDAM, "Read QBG essential params revid:%u\n", *revid); return rc; } int qbg_sdam_set_essential_param_revid(struct qti_qbg *chip, u8 revid) { int rc; if (!chip) return -EINVAL; rc = qbg_sdam_write(chip, chip->sdam_base + (SDAM_CTRL1 * QBG_SINGLE_SDAM_SIZE) + QBG_ESSENTIAL_PARAMS_REVID_OFFSET, &revid, 1); if (rc < 0) pr_err("Failed to write QBG essential params revid, rc=%d\n", rc); else qbg_dbg(chip, QBG_DEBUG_SDAM, "Store QBG essential params revid:%u\n", revid); return rc; } int qbg_sdam_get_battery_id(struct qti_qbg *chip, u32 *battid) { int rc; u8 buf[2]; if (!chip || !battid) return -EINVAL; rc = qbg_sdam_read(chip, chip->sdam_base + (SDAM_CTRL1 * QBG_SINGLE_SDAM_SIZE) + QBG_ESSENTIAL_PARAMS_BATTID_OFFSET, buf, 2); if (rc < 0) { pr_err("Failed to read QBG battery ID, rc=%d\n", rc); } else { *battid = buf[0] | (buf[1] << 8); qbg_dbg(chip, QBG_DEBUG_SDAM, "Read QBG battery ID:%u\n", *battid); } return rc; } int qbg_sdam_set_battery_id(struct qti_qbg *chip, u32 battid) { int rc; if (!chip) return -EINVAL; rc = qbg_sdam_write(chip, chip->sdam_base + (SDAM_CTRL1 * QBG_SINGLE_SDAM_SIZE) + QBG_ESSENTIAL_PARAMS_BATTID_OFFSET, (u8 *)&battid, 2); if (rc < 0) pr_err("Failed to write QBG battery ID, rc=%d\n", rc); else qbg_dbg(chip, QBG_DEBUG_SDAM, "Store QBG battery ID:%u\n", battid); return rc; }