215 lines
5 KiB
C
215 lines
5 KiB
C
// 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 <linux/cdev.h>
|
|
#include <linux/device.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/nvmem-consumer.h>
|
|
#include <linux/regmap.h>
|
|
|
|
#include <uapi/linux/qbg.h>
|
|
|
|
#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;
|
|
}
|