Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c7a5971c authored by Hardik Kantilal Patel's avatar Hardik Kantilal Patel
Browse files

wcnss: Add support to read the Battery voltage



Get Battery voltage from vadc at boot time. If Battery voltage
is less then 3.5V then configure VDD_PA with 3.0V instead of
3.3V. Send indication of current battery voltage to WCNSS FW.

Change-Id: I5470f218c8e136ed12d9aa0b9892a9b53ea6d9f4
CRs-Fixed: 794209
Signed-off-by: default avatarHardik Kantilal Patel <hkpatel@codeaurora.org>
parent 00923319
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ Required properties:
- qcom,has-48mhz-xo: boolean flag to determine the usage of 24MHz XO from RF
- qcom,has-pronto-hw: boolean flag to determine the revId of the WLAN subsystem
- qcom,wcnss-adc_tm: ADC handle for vbatt notification APIs.
- qcom,wcnss-vadc: VADC handle for battery voltage notification APIs.
- pinctrl-<n> : Pinctrl states as described in bindings/pinctrl/pinctrl-bindings.txt
- pinctrl-names : Names corresponding to the numbered pinctrl states
- clocks: from common clock binding: handle to xo and rf_clk clocks.
+33 −3
Original line number Diff line number Diff line
@@ -67,15 +67,16 @@ static int is_power_on;
#define VREG_SET_VOLTAGE_MASK       0x0002
#define VREG_OPTIMUM_MODE_MASK      0x0004
#define VREG_ENABLE_MASK            0x0008
#define VDD_PA                      "qcom,iris-vddpa"

#define WCNSS_INVALID_IRIS_REG      0xbaadbaad

struct vregs_info {
	const char * const name;
	int state;
	const int nominal_min;
	const int low_power_min;
	const int max_voltage;
	int nominal_min;
	int low_power_min;
	int max_voltage;
	const int uA_load;
	struct regulator *regulator;
};
@@ -467,6 +468,14 @@ fail:
static void wcnss_vregs_off(struct vregs_info regulators[], uint size)
{
	int i, rc = 0;
	struct wcnss_wlan_config *cfg;

	cfg = wcnss_get_wlan_config();

	if (!cfg) {
		pr_err("Failed to get WLAN configuration\n");
		return;
	}

	/* Regulators need to be turned off in the reverse order */
	for (i = (size-1); i >= 0; i--) {
@@ -484,6 +493,12 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size)

		/* Set voltage to lowest level */
		if (regulators[i].state & VREG_SET_VOLTAGE_MASK) {
			if (cfg->vbatt < WCNSS_VBATT_THRESHOLD &&
			    !memcmp(regulators[i].name,
				VDD_PA, sizeof(VDD_PA))) {
				regulators[i].max_voltage = WCNSS_VBATT_LOW;
			}

			rc = regulator_set_voltage(regulators[i].regulator,
					regulators[i].low_power_min,
					regulators[i].max_voltage);
@@ -513,6 +528,14 @@ static int wcnss_vregs_on(struct device *dev,
		struct vregs_info regulators[], uint size)
{
	int i, rc = 0, reg_cnt;
	struct wcnss_wlan_config *cfg;

	cfg = wcnss_get_wlan_config();

	if (!cfg) {
		pr_err("Failed to get WLAN configuration\n");
		return -EINVAL;
	}

	for (i = 0; i < size; i++) {
			/* Get regulator source */
@@ -529,6 +552,13 @@ static int wcnss_vregs_on(struct device *dev,
		/* Set voltage to nominal. Exclude swtiches e.g. LVS */
		if ((regulators[i].nominal_min || regulators[i].max_voltage)
				&& (reg_cnt > 0)) {
			if (cfg->vbatt < WCNSS_VBATT_THRESHOLD &&
			    !memcmp(regulators[i].name,
				VDD_PA, sizeof(VDD_PA))) {
				regulators[i].nominal_min = WCNSS_VBATT_INITIAL;
				regulators[i].max_voltage = WCNSS_VBATT_LOW;
			}

			rc = regulator_set_voltage(regulators[i].regulator,
					regulators[i].nominal_min,
					regulators[i].max_voltage);
+66 −5
Original line number Diff line number Diff line
@@ -180,10 +180,6 @@ static DEFINE_SPINLOCK(reg_spinlock);
#define MCU_FDBR_FDAHB_TIMEOUT_OFFSET		0x3ac

#define WCNSS_DEF_WLAN_RX_BUFF_COUNT		1024
#define WCNSS_VBATT_THRESHOLD		3500000
#define WCNSS_VBATT_GUARD		20000
#define WCNSS_VBATT_HIGH		3700000
#define WCNSS_VBATT_LOW			3300000

#define WCNSS_CTRL_CHANNEL			"WCNSS_CTRL"
#define WCNSS_MAX_FRAME_SIZE		(4*1024)
@@ -387,6 +383,7 @@ static struct {
	struct work_struct wcnss_pm_config_work;
	struct work_struct wcnssctrl_nvbin_dnld_work;
	struct work_struct wcnssctrl_rx_work;
	struct work_struct wcnss_vadc_work;
	struct wake_lock wcnss_wake_lock;
	void __iomem *msm_wcnss_base;
	void __iomem *riva_ccu_base;
@@ -422,6 +419,7 @@ static struct {
	wait_queue_head_t read_wait;
	struct qpnp_adc_tm_btm_param vbat_monitor_params;
	struct qpnp_adc_tm_chip *adc_tm_dev;
	struct qpnp_vadc_chip *vadc_dev;
	struct mutex vbat_monitor_mutex;
	u16 unsafe_ch_count;
	u16 unsafe_ch_list[WCNSS_MAX_CH_NUM];
@@ -1279,7 +1277,8 @@ static void wcnss_smd_notify_event(void *data, unsigned int event)
		schedule_work(&penv->wcnss_pm_config_work);
		cancel_delayed_work(&penv->wcnss_pm_qos_del_req);
		schedule_delayed_work(&penv->wcnss_pm_qos_del_req, 0);

		if (penv->wlan_config.is_pronto_v3 && (penv->vadc_dev))
			schedule_work(&penv->wcnss_vadc_work);
		break;

	case SMD_EVENT_CLOSE:
@@ -1858,6 +1857,30 @@ static int wcnss_smd_tx(void *data, int len)
	return ret;
}

static int wcnss_get_battery_volt(int *result_uv)
{
	int rc = -1;
	struct qpnp_vadc_result adc_result;

	if (!penv->vadc_dev) {
		pr_err("wcnss: not setting up vadc\n");
		return rc;
	}

	rc = qpnp_vadc_read(penv->vadc_dev, VBAT_SNS, &adc_result);
	if (rc) {
		pr_err("error reading adc channel = %d, rc = %d\n",
		       VBAT_SNS, rc);
		return rc;
	}

	pr_info("Battery mvolts phy=%lld meas=0x%llx\n", adc_result.physical,
		adc_result.measurement);
	*result_uv = (int)adc_result.physical;

	return 0;
}

static void wcnss_notify_vbat(enum qpnp_tm_state state, void *ctx)
{
	int rc = 0;
@@ -1933,6 +1956,26 @@ static int wcnss_setup_vbat_monitoring(void)
	return rc;
}

static void wcnss_send_vbatt_indication(struct work_struct *work)
{
	struct vbatt_message vbatt_msg;
	int ret = 0;

	vbatt_msg.hdr.msg_type = WCNSS_VBATT_LEVEL_IND;
	vbatt_msg.hdr.msg_len = sizeof(struct vbatt_message);
	vbatt_msg.vbatt.threshold = WCNSS_VBATT_THRESHOLD;

	mutex_lock(&penv->vbat_monitor_mutex);
	vbatt_msg.vbatt.curr_volt = penv->wlan_config.vbatt;
	mutex_unlock(&penv->vbat_monitor_mutex);
	pr_debug("wcnss: send curr_volt: %d to FW\n",
		 vbatt_msg.vbatt.curr_volt);

	ret = wcnss_smd_tx(&vbatt_msg, vbatt_msg.hdr.msg_len);
	if (ret < 0)
		pr_err("wcnss: smd tx failed\n");
}

static void wcnss_update_vbatt(struct work_struct *work)
{
	struct vbatt_message vbatt_msg;
@@ -2658,6 +2701,7 @@ static int
wcnss_trigger_config(struct platform_device *pdev)
{
	int ret;
	int rc;
	struct qcom_wcnss_opts *pdata;
	struct resource *res;
	int is_pronto_vt;
@@ -2992,6 +3036,23 @@ wcnss_trigger_config(struct platform_device *pdev)
		penv->fw_vbatt_state = WCNSS_CONFIG_UNSPECIFIED;
	}

	if (penv->wlan_config.is_pronto_v3) {
		penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss");

		if (IS_ERR(penv->vadc_dev)) {
			pr_err("%s:  vadc get failed\n", __func__);
			penv->vadc_dev = NULL;
		} else {
			rc = wcnss_get_battery_volt(&penv->wlan_config.vbatt);
			INIT_WORK(&penv->wcnss_vadc_work,
				  wcnss_send_vbatt_indication);

			if (rc < 0)
				pr_err("Failed to get battery voltage with error= %d\n",
				       rc);
		}
	}

	do {
		/* trigger initialization of the WCNSS */
		penv->pil = subsystem_get(WCNSS_PIL_DEVICE);
+6 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct wcnss_wlan_config {
	int	is_pronto_v3;
	void __iomem	*msm_wcnss_base;
	int	iris_id;
	int	vbatt;
};

enum {
@@ -49,6 +50,11 @@ enum {
	WCNSS_WLAN_MAX_GPIO,
};

#define WCNSS_VBATT_THRESHOLD           3500000
#define WCNSS_VBATT_GUARD               20000
#define WCNSS_VBATT_HIGH                3700000
#define WCNSS_VBATT_LOW                 3300000
#define WCNSS_VBATT_INITIAL             3000000
#define WCNSS_WLAN_IRQ_INVALID -1
#define HAVE_WCNSS_SUSPEND_RESUME_NOTIFY 1
#define HAVE_WCNSS_RESET_INTR 1