diff --git a/drivers/power/mmi_qc3p_wt6670f/wt6670f_qc3p.c b/drivers/power/mmi_qc3p_wt6670f/wt6670f_qc3p.c index a1f4dd0b0611..556e226a1d5e 100644 --- a/drivers/power/mmi_qc3p_wt6670f/wt6670f_qc3p.c +++ b/drivers/power/mmi_qc3p_wt6670f/wt6670f_qc3p.c @@ -25,6 +25,9 @@ static DEFINE_MUTEX(wt6670f_i2c_access); //static int wt6670f_reset_pin = -1; static int wt6670f_int_pin = -1; struct wt6670f *_wt = NULL; +int g_qc3p_id = 0; +int m_chg_type = 0; +bool qc3p_z350_init_ok = false; static int __wt6670f_write_word(struct wt6670f *wt, u8 reg, u16 data) { @@ -79,11 +82,15 @@ static int wt6670f_write_word(struct wt6670f *wt, u8 reg, u16 data) static u16 wt6670f_get_vbus_voltage(void) { - int ret; + int ret = 0; u8 data[2]; u16 tmp; - - ret = wt6670f_read_word(_wt, 0xBE, (u16 *)data); + if(QC3P_WT6670F == g_qc3p_id) + ret = wt6670f_read_word(_wt, 0xBE, (u16 *)data); + else if(QC3P_Z350 == g_qc3p_id) + ret = wt6670f_read_word(_wt, 0x12, (u16 *)data); + else + ret = -1; if(ret < 0) { pr_err("wt6670f get vbus voltage fail\n"); @@ -97,13 +104,13 @@ static u16 wt6670f_get_vbus_voltage(void) return (u16)(tmp * 18.98); } -/* -static u16 wt6670f_get_id(void) +static u16 wt6670f_get_id(u8 reg) { int ret; u16 data; - ret = wt6670f_read_word(_wt, 0xBC, &data); + ret = wt6670f_read_word(_wt, reg, &data);//wt6670f-0xBC,Z350-0x13 + if(ret < 0) { pr_err("wt6670f get id fail\n"); @@ -113,7 +120,6 @@ static u16 wt6670f_get_id(void) pr_err(">>>>>>wt6670f get id = %x\n", data); return data; } -*/ int wt6670f_start_detection(void) { @@ -148,13 +154,39 @@ int wt6670f_re_run_apsd(void) } EXPORT_SYMBOL_GPL(wt6670f_re_run_apsd); -int wt6670f_get_protocol(void) +int wt6670f_en_hvdcp(void) { int ret; - u16 data; - u8 data1, data2; + u16 data = 0x01; + + ret = wt6670f_write_word(_wt, 0x05, data); + + if (ret < 0) + { + pr_info("z350 en hvdcp fail\n"); + return ret; + } + + return data & 0xff; +} +EXPORT_SYMBOL_GPL(wt6670f_en_hvdcp); + +int wt6670f_get_protocol(void) +{ + int ret = 0; + u16 data; + u8 data1, data2; + if(QC3P_WT6670F == g_qc3p_id){ + ret = wt6670f_read_word(_wt, 0xBD, &data); + pr_err("wt6670f get protocol %x\n",data); + } + else if(QC3P_Z350 == g_qc3p_id){ + ret = wt6670f_read_word(_wt, 0x11, &data); + pr_err("z350 get protocol %x\n",data); + } + else + ret = -1; - ret = wt6670f_read_word(_wt, 0xBD, &data); if (ret < 0) { pr_err("wt6670f get protocol fail\n"); @@ -164,7 +196,8 @@ int wt6670f_get_protocol(void) // Get data2 part data1 = data & 0xFF; data2 = data >> 8; - + if((QC3P_Z350 == g_qc3p_id)&&(data1 <= 7)) + data1--; pr_err("Get charger type, rowdata = 0X%04x, data1= 0X%02x, data2=0X%02x \n", data, data1, data2); if((data2 == 0x03) && ((data1 > 0x9) || (data1 == 0x7))) { @@ -178,7 +211,7 @@ int wt6670f_get_protocol(void) } if((data1 > 0x00 && data1 < 0x07) || - (data1 > 0x07 && data1 < 0x0a)){ + (data1 > 0x07 && data1 < 0x0a) ||(QC3P_Z350 == g_qc3p_id && data1 == 0x10)){ ret = data1; } else { @@ -220,9 +253,23 @@ int wt6670f_get_firmware_version(void) EXPORT_SYMBOL_GPL(wt6670f_get_firmware_version); -int wt6670f_set_voltage(u16 voltage) +int z350_get_firmware_version(void) { int ret; + u16 data; + + ret = wt6670f_read_word(_wt, 0x14, &data); + if (ret < 0) + { + pr_err("z350 get firmware fail\n"); + return ret; + } + return data; +} + +int wt6670f_set_voltage(u16 voltage) +{ + int ret = 0; u16 step; u16 voltage_now; @@ -246,8 +293,14 @@ int wt6670f_set_voltage(u16 voltage) step |= 0x8000; step = ((step & 0xff) << 8) | ((step >> 8) & 0xff); } - pr_err("---->southchip count = %d %04x\n", _wt->count, step); - ret = wt6670f_write_word(_wt, 0xBB, step); + pr_err("---->southchip count = %d %04x,QC3P_WT6670F=%d,g_qc3p_id=%d,voltage=%d,voltage_now=%d\n", _wt->count, step,QC3P_WT6670F,g_qc3p_id,voltage,voltage_now); + + if(QC3P_WT6670F == g_qc3p_id) + ret = wt6670f_write_word(_wt, 0xBB, step); + else if(QC3P_Z350 == g_qc3p_id) + ret = wt6670f_write_word(_wt, 0x83, step); + else + ret = -1; return ret; } @@ -255,7 +308,7 @@ EXPORT_SYMBOL_GPL(wt6670f_set_voltage); int wt6670f_set_volt_count(int count) { - int ret; + int ret = 0; u16 step = abs(count); pr_err("Set vbus with %d pulse!\n!", count); @@ -275,8 +328,11 @@ int wt6670f_set_volt_count(int count) step |= 0x8000; step = ((step & 0xff) << 8) | ((step >> 8) & 0xff); } - pr_err("---->southchip count = %d %04x\n", _wt->count, step); - ret = wt6670f_write_word(_wt, 0xBB, step); + + if(QC3P_WT6670F == g_qc3p_id) + ret = wt6670f_write_word(_wt, 0xBB, step); + else if(QC3P_Z350 == g_qc3p_id) + ret = wt6670f_write_word(_wt, 0x83, step); return ret; } @@ -318,12 +374,20 @@ static ssize_t wt6670f_show_registers(struct device *dev, struct wt6670f *wt = dev_get_drvdata(dev); int idx = 0; - int ret ; + int ret = 0; u16 data; + if(QC3P_WT6670F == g_qc3p_id){ + ret = wt6670f_read_word(wt, 0xBD, &data); + idx = snprintf(buf, PAGE_SIZE, ">>> reg[0xBD] = %04x\n", data); + pr_err(">>>>>>>>>>WT6670F test southchip 0xBD = %04x\n", data); + } + + if(QC3P_Z350 == g_qc3p_id){ + ret = wt6670f_read_word(wt, 0x11, &data); + idx = snprintf(buf, PAGE_SIZE, ">>> reg[0x11] = %04x\n", data); + pr_err(">>>>>>>>>>Z350 test southchip 0x11 = %04x\n", data); + } - ret = wt6670f_read_word(wt, 0xBD, &data); - idx = snprintf(buf, PAGE_SIZE, ">>> reg[0xBD] = %04x\n", data); - pr_err(">>>>>>>>>>test southchip 0xBD = %04x\n", data); return idx; } @@ -333,11 +397,15 @@ static ssize_t wt6670f_store_registers(struct device *dev, struct wt6670f *wt = dev_get_drvdata(dev); int val; - int ret; + int ret = 0; ret = sscanf(buf, "%x", &val); - ret = wt6670f_write_word(wt, 0xBB, val); + if(QC3P_WT6670F == g_qc3p_id) + ret = wt6670f_write_word(wt, 0xBB, val); + + if(QC3P_Z350 == g_qc3p_id) + ret = wt6670f_write_word(wt, 0x83, val); return count; @@ -384,11 +452,13 @@ EXPORT_SYMBOL_GPL(wt6670f_reset_chg_type); int moto_tcmd_wt6670f_get_firmware_version(void) { - int fm_ver = 0; + int wt6670f_fm_ver = 0; + int z350_fm_ver = 0; wt6670f_do_reset(); - fm_ver = wt6670f_get_firmware_version(); - pr_info("%s: wt6670f get firmware:%d!\n", __func__,fm_ver); - if(3 == fm_ver) + wt6670f_fm_ver = wt6670f_get_firmware_version(); + z350_fm_ver = z350_get_firmware_version(); + pr_info("%s: get firmware wt6670f:%x,z350:%x!\n", __func__,wt6670f_fm_ver,z350_fm_ver); + if((3 == wt6670f_fm_ver)||(0x080a == z350_fm_ver)||(0x0f0a == z350_fm_ver)) return 1; else return 0; @@ -397,7 +467,8 @@ EXPORT_SYMBOL_GPL(moto_tcmd_wt6670f_get_firmware_version); static irqreturn_t wt6670f_intr_handler(int irq, void *data) { - pr_info("%s: read charger type!\n", __func__); + m_chg_type = 0xff; + pr_info("%s,chg_type 0x:%x\n", __func__,m_chg_type); _wt->chg_ready = true; return IRQ_HANDLED; @@ -477,8 +548,10 @@ static int wt6670_iio_read_raw(struct iio_dev *indio_dev, { int rc = 0; int result; + int wait_count = 0; *val1 = 0; + switch (chan->channel) { case PSY_IIO_QC3P_POWER: result = wt6670f_get_charger_type(); @@ -489,6 +562,19 @@ static int wt6670_iio_read_raw(struct iio_dev *indio_dev, case PSY_IIO_QC3P_REAL_TYPE: wt6670f_get_protocol(); result = wt6670f_get_charger_type(); + + if((result == 0x10) &&(QC3P_Z350 == g_qc3p_id)) { + wt6670f_en_hvdcp(); + pr_info("wt6670 wt6670f_en_hvdcp\n"); + wait_count = 0; + while((result != 0xff)&&(wait_count<30)){ + msleep(100); + wait_count++; + } + wt6670f_get_protocol(); + result = wt6670f_get_charger_type(); + } + pr_info("wt6670 get charger type:%d\n", result); *val1 = result; break; @@ -502,8 +588,18 @@ static int wt6670_iio_read_raw(struct iio_dev *indio_dev, usleep_range(5000,6000); gpio_direction_output(_wt->intb_pin,1); usleep_range(5000,6000); - result = wt6670f_get_firmware_version(); - pr_info("wt6670 get wt6670f_firmware_num:%d\n", result); + + if(QC3P_WT6670F == g_qc3p_id){ + result = wt6670f_get_firmware_version(); + pr_info("wt6670 get wt6670f_firmware_num:%d\n", result); + } else if(QC3P_Z350 == g_qc3p_id){ + result = z350_get_firmware_version(); + pr_info("z350 get z350_get_firmware_version:0x%x\n", result); + } else { + result = 0; + pr_info("could not get device id for used\n"); + } + *val1 = result; gpio_direction_input(wt6670f_int_pin); break; @@ -599,6 +695,7 @@ static int wt6670f_i2c_probe(struct i2c_client *client, { int ret = 0; u16 firmware_version = 0; + u16 wt6670f_id = 0; int in_isp_flow_count = 3; struct wt6670f *wt; struct iio_dev *indio_dev; @@ -630,6 +727,28 @@ static int wt6670f_i2c_probe(struct i2c_client *client, wt6670f_create_device_node(&(client->dev)); //wt6670f_do_reset(); + + gpio_direction_output(_wt->reset_pin,1); + usleep_range(5000,6000); + gpio_direction_output(_wt->reset_pin,0); + usleep_range(5000,6000); + + wt6670f_id = wt6670f_get_id(0x13); + if(0x3349 == wt6670f_id){ + g_qc3p_id = QC3P_Z350; + qc3p_z350_init_ok = true; + //gpio_direction_output(_wt->reset_pin, 1); + pr_info("[%s] wt is z350\n", __func__); + + ret = wt6670_init_iio_psy(wt); + if (ret < 0) + pr_info("%s: init iio sys error\n", __func__); + + if (gpio_direction_input(wt6670f_int_pin)) + pr_info("[%s] gpio_direction_input wt6670f_int_pin failed", __func__); + goto probe_out; + } + wt6670f_reset_chg_type(); gpio_direction_output(_wt->intb_pin,0); usleep_range(5000,6000); @@ -647,19 +766,40 @@ static int wt6670f_i2c_probe(struct i2c_client *client, break; } } + wt6670f_id = wt6670f_get_id(0xBC); + if(0x5457 == wt6670f_id){ + g_qc3p_id = QC3P_WT6670F; + pr_info("[%s] is wt6670f,firmware_version = %x\n", __func__,firmware_version); + } ret = wt6670_init_iio_psy(wt); if (ret < 0) pr_info("%s: init iio sys error\n", __func__); if (gpio_direction_input(wt6670f_int_pin)) pr_info("[%s] gpio_direction_input wt6670f_int_pin failed", __func__); +probe_out: return 0; } static void wt6670f_shutdown(struct i2c_client *client) { - //wt6670f_start_detection(); - pr_info("%s\n", __func__); + int ret = 0; + u16 data = 0x01; + + if(QC3P_WT6670F == g_qc3p_id){ + ret = wt6670f_write_word(_wt, 0xB6, data); + pr_info("%s set voltage ok wt6670\n", __func__); + }else if(QC3P_Z350 == g_qc3p_id){ + ret = wt6670f_write_word(_wt, 0x02, data); + pr_info("%s set voltage ok z350\n", __func__); + }else{ + ret = wt6670f_write_word(_wt, 0xB6, data); + pr_info("%s set voltage ok wt6670\n", __func__); + } + if (ret < 0) + { + pr_info("%s set voltage fail\n",__func__); + } } //#define WT6670F_PM_OPS (NULL)