mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-25 06:03:36 -04:00
Merge "icnss2: Add open loop CPR support"
This commit is contained in:
commit
f9790cb371
4 changed files with 147 additions and 0 deletions
|
|
@ -3267,6 +3267,7 @@ static int icnss_probe(struct platform_device *pdev)
|
|||
icnss_pr_err("ICNSS genl init failed %d\n", ret);
|
||||
|
||||
icnss_runtime_pm_init(priv);
|
||||
icnss_get_cpr_info(priv);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&priv->icnss_tcdev_list);
|
||||
|
|
|
|||
|
|
@ -133,6 +133,15 @@ struct icnss_vreg_info {
|
|||
u32 enabled;
|
||||
};
|
||||
|
||||
struct icnss_cpr_info {
|
||||
resource_size_t tcs_cmd_base_addr;
|
||||
resource_size_t tcs_cmd_data_addr;
|
||||
void __iomem *tcs_cmd_base_addr_io;
|
||||
void __iomem *tcs_cmd_data_addr_io;
|
||||
u32 cpr_pmic_addr;
|
||||
u32 voltage;
|
||||
};
|
||||
|
||||
enum icnss_vreg_type {
|
||||
ICNSS_VREG_PRIM,
|
||||
};
|
||||
|
|
@ -307,6 +316,7 @@ struct icnss_priv {
|
|||
struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS];
|
||||
struct list_head vreg_list;
|
||||
struct list_head clk_list;
|
||||
struct icnss_cpr_info cpr_info;
|
||||
unsigned long device_id;
|
||||
struct icnss_msi_config *msi_config;
|
||||
u32 msi_base_data;
|
||||
|
|
@ -419,5 +429,7 @@ int icnss_soc_wake_event_post(struct icnss_priv *priv,
|
|||
u32 flags, void *data);
|
||||
int icnss_get_iova(struct icnss_priv *priv, u64 *addr, u64 *size);
|
||||
int icnss_get_iova_ipa(struct icnss_priv *priv, u64 *addr, u64 *size);
|
||||
int icnss_get_cpr_info(struct icnss_priv *priv);
|
||||
int icnss_update_cpr_info(struct icnss_priv *priv);
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <soc/qcom/cmd-db.h>
|
||||
#include <linux/io.h>
|
||||
#include "main.h"
|
||||
#include "qmi.h"
|
||||
#include "debug.h"
|
||||
|
|
@ -45,6 +46,13 @@ static struct icnss_clk_cfg icnss_adrestea_clk_list[] = {
|
|||
#define ICNSS_THRESHOLD_LOW 3450000
|
||||
#define ICNSS_THRESHOLD_GUARD 20000
|
||||
|
||||
#define TCS_CMD_DATA_ADDR_OFFSET 0x4
|
||||
#define TCS_OFFSET 0xC8
|
||||
#define TCS_CMD_OFFSET 0x10
|
||||
#define MAX_TCS_NUM 8
|
||||
#define MAX_TCS_CMD_NUM 5
|
||||
#define BT_CXMX_VOLTAGE_MV 950
|
||||
|
||||
static int icnss_get_vreg_single(struct icnss_priv *priv,
|
||||
struct icnss_vreg_info *vreg)
|
||||
{
|
||||
|
|
@ -801,3 +809,121 @@ int icnss_init_vph_monitor(struct icnss_priv *priv)
|
|||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int icnss_get_cpr_info(struct icnss_priv *priv)
|
||||
{
|
||||
struct platform_device *plat_dev = priv->pdev;
|
||||
struct icnss_cpr_info *cpr_info = &priv->cpr_info;
|
||||
struct resource *res;
|
||||
resource_size_t addr_len;
|
||||
void __iomem *tcs_cmd_base_addr;
|
||||
const char *cmd_db_name;
|
||||
u32 cpr_pmic_addr = 0;
|
||||
int ret = 0;
|
||||
|
||||
res = platform_get_resource_byname(plat_dev, IORESOURCE_MEM, "tcs_cmd");
|
||||
if (!res) {
|
||||
icnss_pr_dbg("TCS CMD address is not present for CPR\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = of_property_read_string(plat_dev->dev.of_node,
|
||||
"qcom,cmd_db_name", &cmd_db_name);
|
||||
if (ret) {
|
||||
icnss_pr_dbg("CommandDB name is not present for CPR\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpr_pmic_addr = cmd_db_read_addr(cmd_db_name);
|
||||
if (cpr_pmic_addr > 0) {
|
||||
cpr_info->cpr_pmic_addr = cpr_pmic_addr;
|
||||
icnss_pr_dbg("Get CPR PMIC address 0x%x from %s\n",
|
||||
cpr_info->cpr_pmic_addr, cmd_db_name);
|
||||
} else {
|
||||
icnss_pr_err("CPR PMIC address is not available for %s\n",
|
||||
cmd_db_name);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpr_info->tcs_cmd_base_addr = res->start;
|
||||
addr_len = resource_size(res);
|
||||
icnss_pr_dbg("TCS CMD base address is %pa with length %pa\n",
|
||||
&cpr_info->tcs_cmd_base_addr, &addr_len);
|
||||
|
||||
tcs_cmd_base_addr = devm_ioremap_resource(&plat_dev->dev, res);
|
||||
if (IS_ERR(tcs_cmd_base_addr)) {
|
||||
ret = PTR_ERR(tcs_cmd_base_addr);
|
||||
icnss_pr_err("Failed to map TCS CMD address, err = %d\n",
|
||||
ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
cpr_info->tcs_cmd_base_addr_io = tcs_cmd_base_addr;
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int icnss_update_cpr_info(struct icnss_priv *priv)
|
||||
{
|
||||
struct icnss_cpr_info *cpr_info = &priv->cpr_info;
|
||||
u32 pmic_addr, voltage = 0, voltage_tmp, offset;
|
||||
void __iomem *tcs_cmd_addr, *tcs_cmd_data_addr;
|
||||
int i, j;
|
||||
|
||||
if (cpr_info->tcs_cmd_base_addr == 0) {
|
||||
icnss_pr_dbg("CPR is not enabled\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cpr_info->voltage == 0 || cpr_info->cpr_pmic_addr == 0) {
|
||||
icnss_pr_err("Voltage %dmV or PMIC address 0x%x is not valid\n",
|
||||
cpr_info->voltage, cpr_info->cpr_pmic_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cpr_info->tcs_cmd_data_addr_io)
|
||||
goto update_cpr;
|
||||
|
||||
for (i = 0; i < MAX_TCS_NUM; i++) {
|
||||
for (j = 0; j < MAX_TCS_CMD_NUM; j++) {
|
||||
offset = i * TCS_OFFSET + j * TCS_CMD_OFFSET;
|
||||
tcs_cmd_addr = cpr_info->tcs_cmd_base_addr_io + offset;
|
||||
pmic_addr = readl_relaxed(tcs_cmd_addr);
|
||||
if (pmic_addr == cpr_info->cpr_pmic_addr) {
|
||||
tcs_cmd_data_addr = tcs_cmd_addr +
|
||||
TCS_CMD_DATA_ADDR_OFFSET;
|
||||
voltage_tmp = readl_relaxed(tcs_cmd_data_addr);
|
||||
icnss_pr_dbg("Got voltage %dmV from i: %d, j: %d\n",
|
||||
voltage_tmp, i, j);
|
||||
|
||||
if (voltage_tmp > voltage) {
|
||||
voltage = voltage_tmp;
|
||||
cpr_info->tcs_cmd_data_addr =
|
||||
cpr_info->tcs_cmd_base_addr +
|
||||
offset +
|
||||
TCS_CMD_DATA_ADDR_OFFSET;
|
||||
cpr_info->tcs_cmd_data_addr_io =
|
||||
tcs_cmd_data_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cpr_info->tcs_cmd_data_addr_io) {
|
||||
icnss_pr_err("Failed to find proper TCS CMD data address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
update_cpr:
|
||||
cpr_info->voltage = cpr_info->voltage > BT_CXMX_VOLTAGE_MV ?
|
||||
cpr_info->voltage : BT_CXMX_VOLTAGE_MV;
|
||||
icnss_pr_dbg("Update TCS CMD data address %pa with voltage %dmV\n",
|
||||
&cpr_info->tcs_cmd_data_addr, cpr_info->voltage);
|
||||
writel_relaxed(cpr_info->voltage, cpr_info->tcs_cmd_data_addr_io);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -674,6 +674,14 @@ int wlfw_cap_send_sync_msg(struct icnss_priv *priv)
|
|||
resp->fw_version_info.fw_build_timestamp,
|
||||
WLFW_MAX_TIMESTAMP_LEN + 1);
|
||||
}
|
||||
|
||||
if (resp->voltage_mv_valid) {
|
||||
priv->cpr_info.voltage = resp->voltage_mv;
|
||||
icnss_pr_dbg("Voltage for CPR: %dmV\n",
|
||||
priv->cpr_info.voltage);
|
||||
icnss_update_cpr_info(priv);
|
||||
}
|
||||
|
||||
if (resp->fw_build_id_valid)
|
||||
strlcpy(priv->fw_build_id, resp->fw_build_id,
|
||||
QMI_WLFW_MAX_BUILD_ID_LEN_V01 + 1);
|
||||
|
|
|
|||
Loading…
Reference in a new issue