icnss2: Enable power supply framework for 5.15 kernel

Icnss driver indicates vbatt voltage level to wlan fw
based on battery percentage. This change adds power
supply framework code to enable icnss2 driver to measure
battery percentage and update vbatt volatge level to
wlan fw.

Change-Id: I376805da38222a5e7a20ae4a1737bc978ee6a9ae
Signed-off-by: Sandeep Singh <quic_sandsing@quicinc.com>
Este commit está contenido en:
Sandeep Singh
2022-05-25 11:56:02 +05:30
padre 2aa767ca86
commit 9be6cc9072
Se han modificado 6 ficheros con 227 adiciones y 1 borrados

Ver fichero

@@ -30,6 +30,14 @@ static struct icnss_vreg_cfg icnss_adrestea_vreg_list[] = {
{"vdd-3.3-ch0", 3312000, 3312000, 0, 0, 0, false, true},
};
static struct icnss_battery_level icnss_battery_level[] = {
{70, 3300000},
{60, 3200000},
{50, 3100000},
{25, 3000000},
{0, 2850000},
};
static struct icnss_clk_cfg icnss_clk_list[] = {
{"rf_clk", 0, 0},
};
@@ -50,6 +58,9 @@ static struct icnss_clk_cfg icnss_adrestea_clk_list[] = {
#define ICNSS_MBOX_MSG_MAX_LEN 64
#define ICNSS_MBOX_TIMEOUT_MS 1000
#define ICNSS_BATTERY_LEVEL_COUNT ARRAY_SIZE(icnss_battery_level)
#define ICNSS_MAX_BATTERY_LEVEL 100
/**
* enum icnss_vreg_param: Voltage regulator TCS param
* @ICNSS_VREG_VOLTAGE: Provides voltage level to be configured in TCS
@@ -808,3 +819,107 @@ int icnss_update_cpr_info(struct icnss_priv *priv)
ICNSS_TCS_UP_SEQ,
cpr_info->voltage);
}
static int icnss_get_battery_level(struct icnss_priv *priv)
{
int err = 0, battery_percentage = 0;
union power_supply_propval psp = {0,};
if (!priv->batt_psy)
priv->batt_psy = power_supply_get_by_name("battery");
if (priv->batt_psy) {
err = power_supply_get_property(priv->batt_psy,
POWER_SUPPLY_PROP_CAPACITY,
&psp);
if (err) {
icnss_pr_err("battery percentage read error:%d\n", err);
goto out;
}
battery_percentage = psp.intval;
}
icnss_pr_info("Battery Percentage: %d\n", battery_percentage);
out:
return battery_percentage;
}
static void icnss_update_soc_level(struct work_struct *work)
{
int battery_percentage = 0, current_updated_voltage = 0, err = 0;
int level_count;
struct icnss_priv *priv = container_of(work, struct icnss_priv, soc_update_work);
battery_percentage = icnss_get_battery_level(priv);
if (!battery_percentage ||
battery_percentage > ICNSS_MAX_BATTERY_LEVEL) {
icnss_pr_err("Battery percentage read failure\n");
return;
}
for (level_count = 0; level_count < ICNSS_BATTERY_LEVEL_COUNT;
level_count++) {
if (battery_percentage >=
icnss_battery_level[level_count].lower_battery_threshold) {
current_updated_voltage =
icnss_battery_level[level_count].ldo_voltage;
break;
}
}
if (level_count != ICNSS_BATTERY_LEVEL_COUNT &&
priv->last_updated_voltage != current_updated_voltage) {
err = icnss_send_vbatt_update(priv, current_updated_voltage);
if (err < 0) {
icnss_pr_err("Unable to update ldo voltage");
return;
}
priv->last_updated_voltage = current_updated_voltage;
}
}
static int icnss_battery_supply_callback(struct notifier_block *nb,
unsigned long event, void *data)
{
struct power_supply *psy = data;
struct icnss_priv *priv = container_of(nb, struct icnss_priv,
psf_nb);
if (strcmp(psy->desc->name, "battery"))
return NOTIFY_OK;
if (test_bit(ICNSS_WLFW_CONNECTED, &priv->state) &&
!test_bit(ICNSS_FW_DOWN, &priv->state))
queue_work(priv->soc_update_wq, &priv->soc_update_work);
return NOTIFY_OK;
}
int icnss_get_psf_info(struct icnss_priv *priv)
{
int ret = 0;
priv->soc_update_wq = alloc_workqueue("icnss_soc_update",
WQ_UNBOUND, 1);
if (!priv->soc_update_wq) {
icnss_pr_err("Workqueue creation failed for soc update\n");
ret = -EFAULT;
goto out;
}
priv->psf_nb.notifier_call = icnss_battery_supply_callback;
ret = power_supply_reg_notifier(&priv->psf_nb);
if (ret < 0) {
icnss_pr_err("Power supply framework registration err: %d\n",
ret);
goto err_psf_registration;
}
INIT_WORK(&priv->soc_update_work, icnss_update_soc_level);
return 0;
err_psf_registration:
destroy_workqueue(priv->soc_update_wq);
out:
return ret;
}