p9221_charger: fix IOP test fail

1. use 5.5V for BPP & EPP 5W
2. use 9.5V for EPP Vout
3. set Tx1801 Q factor to 10
4. write Q factor again if not Tx1801
5. use IOP FOD for specific Tx(base on mfg defined in dtsi)

Bug: 289176627
Change-Id: Ib792d986ebd364f80efa6c4f8e07a822b0ccc8de
Signed-off-by: YiHsiang Peng <[email protected]>
diff --git a/p9221_charger.c b/p9221_charger.c
index 9ddfc04..be386ca 100644
--- a/p9221_charger.c
+++ b/p9221_charger.c
@@ -59,6 +59,7 @@
 
 #define P9XXX_VOUT_5480MV	5480
 #define P9XXX_VOUT_5000MV	5000
+#define P9XXX_VOUT_10000MV	10000
 #define P9XXX_FOD_CHK_DELAY_MS	2000
 
 #define P9XXX_SET_RF_DELAY_MS	330
@@ -74,6 +75,7 @@
 	WLC_BPP = 0,
 	WLC_EPP,
 	WLC_EPP_COMP,
+	WLC_EPP_IOP,
 	WLC_HPP,
 	WLC_HPP_HV,
 };
@@ -324,6 +326,20 @@
 
 	return false;
 }
+static int p9xxx_check_iop_fod_by_mfg(struct p9221_charger_data *charger)
+{
+	int i;
+
+	for (i = 0; i < charger->pdata->fod_iop_mfg_num; i++) {
+		if (charger->mfg == charger->pdata->fod_iop_mfg[i]) {
+			dev_info(&charger->client->dev, "mfg is 0x%04x == 0x%04x\n",
+				charger->mfg, charger->pdata->fod_iop_mfg[i]);
+			return WLC_EPP_IOP;
+		}
+	}
+
+	return WLC_EPP;
+}
 
 static int p9221_check_fod_by_fsw(struct p9221_charger_data *charger)
 {
@@ -357,7 +373,7 @@
 	int ret;
 	int retries = 3;
 	int vout_mv;
-	static char *wlc_mode[] = { "BPP", "EPP", "EPP_COMP",
+	static char *wlc_mode[] = { "BPP", "EPP", "EPP_COMP", "EPP_IOP",
 				    "HPP_0", "HPP_1", "HPP_2", "HPP_3",
 				    "HPP_4", "HPP_5", "HPP_6", "HPP_7" };
 
@@ -383,12 +399,17 @@
 		mode = WLC_EPP;
 		if (charger->pdata->fod_fsw)
 			mode = p9221_check_fod_by_fsw(charger);
+		if (charger->pdata->fod_iop_mfg_num > 0)
+			mode = p9xxx_check_iop_fod_by_mfg(charger);
 		if (mode == WLC_EPP) {
 			fod = charger->pdata->fod_epp;
 			fod_count = charger->pdata->fod_epp_num;
 		} else if (mode == WLC_EPP_COMP) {
 			fod = charger->pdata->fod_epp_comp;
 			fod_count = charger->pdata->fod_epp_comp_num;
+		} else if (mode == WLC_EPP_IOP) {
+			fod = charger->pdata->fod_epp_iop;
+			fod_count = charger->pdata->fod_epp_iop_num;
 		}
 	}
 
@@ -3514,6 +3535,26 @@
 	return 0;
 }
 
+static int p9xxx_set_vout_iop(struct p9221_charger_data *charger)
+{
+	int ret = 0;
+	u32 vout_mv;
+
+	ret = charger->chip_get_vout_max(charger, &vout_mv);
+	if (ret < 0)
+		goto exit;
+
+	if (charger->pdata->set_iop_vout_bpp > 0 && vout_mv == P9XXX_VOUT_5000MV)
+		ret = charger->chip_set_vout_max(charger, charger->pdata->set_iop_vout_bpp);
+	else if (charger->pdata->set_iop_vout_epp > 0 && vout_mv == P9XXX_VOUT_10000MV)
+		ret = charger->chip_set_vout_max(charger, charger->pdata->set_iop_vout_epp);
+exit:
+	if (ret < 0)
+		dev_dbg(&charger->client->dev, "Fail to change VOUT\n");
+
+	return ret;
+}
+
 /* 2 P9221_NOTIFIER_DELAY_MS from VRECTON */
 static void p9221_notifier_check_dc(struct p9221_charger_data *charger)
 {
@@ -3545,7 +3586,7 @@
 	}
 
 	dev_info(&charger->client->dev, "dc status is %d\n", dc_in);
-  	charger->check_dc = false;
+	charger->check_dc = false;
 	/*
 	 * We now have confirmation from DC_IN, kill the timer, charger->online
 	 * will be set by this function.
@@ -3601,6 +3642,7 @@
 			charger->sw_ramp_done = true;
 		}
 		p9221_set_dc_icl(charger);
+		p9xxx_set_vout_iop(charger);
 		p9221_write_fod(charger);
 		if (!charger->dc_icl_bpp)
 			p9221_icl_ramp_start(charger);
@@ -3711,6 +3753,14 @@
 				 "update Q factor=%d(mfg=%x)\n",
 				 charger->pdata->tx_4191q, charger->mfg);
 	};
+
+	if (charger->mfg == P9221_PTMC_EPP_TX_1801) {
+		ret = p9xxx_chip_set_q_factor_reg(charger, charger->pdata->tx_1801q);
+		dev_info(&charger->client->dev, "update Q factor=%d(mfg=%x) ret=%d\n",
+			 charger->pdata->tx_1801q, charger->mfg, ret);
+	} else if (charger->pdata->tx_1801q > 0) {
+		p9xxx_write_q_factor(charger);
+	}
 }
 
 static void p9221_notifier_work(struct work_struct *work)
@@ -6374,6 +6424,8 @@
 		return;
 
 	p9xxx_write_resonance_freq(charger);
+
+	p9xxx_update_q_factor(charger);
 }
 
 static void p9xxx_chk_fod_work(struct work_struct *work)
@@ -6675,6 +6727,7 @@
 	p9221_parse_fod(dev, &pdata->fod_num, pdata->fod, "fod");
 	p9221_parse_fod(dev, &pdata->fod_epp_num, pdata->fod_epp, "fod_epp");
 	p9221_parse_fod(dev, &pdata->fod_epp_comp_num, pdata->fod_epp_comp, "fod_epp_comp");
+	p9221_parse_fod(dev, &pdata->fod_epp_iop_num, pdata->fod_epp_iop, "fod_epp_iop");
 
 	nb_hpp_fod_vol = of_property_count_elems_of_size(node, "google,hpp_fod_vol", sizeof(u32));
 	if (nb_hpp_fod_vol > 0) {
@@ -6739,6 +6792,20 @@
 		dev_info(dev, "dt fod_fsw_low_thres:%d\n", pdata->fod_fsw_low);
 	}
 
+	pdata->fod_iop_mfg_num = of_property_count_elems_of_size(node, "google,iop_fod_mfg", sizeof(u16));
+	if (pdata->fod_iop_mfg_num > 0) {
+		if (pdata->fod_iop_mfg_num > P9XXX_IOP_MFG_NUM)
+			pdata->fod_iop_mfg_num = P9XXX_IOP_MFG_NUM;
+		ret = of_property_read_u16_array(node, "google,iop_fod_mfg",
+						 pdata->fod_iop_mfg, pdata->fod_iop_mfg_num);
+		if (ret == 0) {
+			int i;
+
+			for (i = 0; i < pdata->fod_iop_mfg_num; i++)
+				dev_info(dev, "dt google,iop_fod_mfg: 0x%03x \n", pdata->fod_iop_mfg[i]);
+		}
+	}
+
 	ret = of_property_read_u32(node, "google,q_value", &data);
 	if (ret < 0) {
 		pdata->q_value = -1;
@@ -6762,6 +6829,13 @@
 		pdata->tx_4191q = data;
 		dev_info(dev, "dt tx4191_q:%d\n", pdata->tx_4191q);
 	}
+	ret = of_property_read_u32(node, "google,tx1801_q", &data);
+	if (ret < 0) {
+		pdata->tx_1801q = -1;
+	} else {
+		pdata->tx_1801q = data;
+		dev_info(dev, "dt tx1801_q:%d\n", pdata->tx_1801q);
+	}
 
 	ret = of_property_read_u32(node, "google,epp_rp_value", &data);
 	if (ret < 0) {
@@ -6929,6 +7003,19 @@
 	else
 		pdata->align_delta = data;
 
+	ret = of_property_read_u32(node, "google,bpp_iop_vout_mv", &data);
+	if (ret < 0)
+		pdata->set_iop_vout_bpp = 0;
+	else
+		pdata->set_iop_vout_bpp = data;
+
+	ret = of_property_read_u32(node, "google,epp_iop_vout_mv", &data);
+	if (ret < 0)
+		pdata->set_iop_vout_epp = 0;
+	else
+		pdata->set_iop_vout_epp = data;
+
+
 	/* Calibrate light load */
 	pdata->light_load = of_property_read_bool(node, "google,light_load");
 	pdata->ll_vout_not_set = of_property_read_bool(node, "google,ll-bpp-vout-not-set");
diff --git a/p9221_charger.h b/p9221_charger.h
index 0111487..82229e1 100644
--- a/p9221_charger.h
+++ b/p9221_charger.h
@@ -78,6 +78,7 @@
 #define P9221_NEG_POWER_10W		(10 * 2)
 #define P9221_PTMC_EPP_TX_1912		0x32
 #define P9221_PTMC_EPP_TX_4191		0x50
+#define P9221_PTMC_EPP_TX_1801		0x28
 
 #define P9222_RX_CALIBRATION_LIGHT_LOAD	0x5831
 #define P9222_LIGHT_LOAD_VALUE		0x0C
@@ -536,6 +537,8 @@
 
 #define P9412_HPP_FOD_SETS			8
 
+#define P9XXX_IOP_MFG_NUM			8
+
 /* RA9530 */
 
 #define RA9530_CHIP_ID				0x9530
@@ -671,20 +674,25 @@
 	u8				fod[P9221R5_NUM_FOD];
 	u8				fod_epp[P9221R5_NUM_FOD];
 	u8				fod_epp_comp[P9221R5_NUM_FOD];
+	u8				fod_epp_iop[P9221R5_NUM_FOD];
 	u8				fod_hpp[P9221R5_NUM_FOD];
 	u8				fod_hpp_hv[P9221R5_NUM_FOD];
 	struct p9221_fod_data		hpp_fods[P9412_HPP_FOD_SETS];
 	int				fod_num;
 	int				fod_epp_num;
 	int				fod_epp_comp_num;
+	int				fod_epp_iop_num;
 	int				fod_hpp_num;
 	int				fod_hpp_hv_num;
 	bool				fod_fsw;
 	int				fod_fsw_high;
 	int				fod_fsw_low;
+	u16				fod_iop_mfg[P9XXX_IOP_MFG_NUM];
+	int				fod_iop_mfg_num;
 	int				q_value;
 	int				rf_value;
 	int				tx_4191q;
+	int				tx_1801q;
 	int				epp_rp_value;
 	int				epp_rp_low_value;
 	int				needs_dcin_reset;
@@ -721,6 +729,8 @@
 	bool				disable_repeat_eop;
 	bool				bpp_cep_on_dl;
 	bool				hda_tz_wlc;
+	u32				set_iop_vout_bpp;
+	u32				set_iop_vout_epp;
 };
 
 struct p9221_charger_ints_bit {