kernel-brax3-ubuntu-touch/drivers/power/supply/mt5728_wireless_driver-15w.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

3948 lines
No EOL
121 KiB
C
Executable file
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/******************************************************************************
* file MT5728 15W wireless charge driver
* Copyright (C) 2020 prize.
******************************************************************************/
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/timer.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/poll.h>
#include <linux/debugfs.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/of.h>
#include <linux/pinctrl/consumer.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <linux/of_gpio.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>
//#include "mtk_charger_intf.h" //add by sunshuai
//#include <linux/wakelock.h>
//#include <extcon_usb.h>
//#include "mtk_charger.h"
//#include "MT5728_mtp_array.h"
//#include "mtk_charger_intf.h"
//#include "mtk_switch_charging.h"
//#include "mtk_intf.h"
#include "mtk_charger.h"
#include "mtk_battery.h"
#include "mt5728_wireless_15w.h"
//#include <mt-plat/v1/prop_chgalgo_class.h>
#include "charger_class.h"
//#include <mt-plat/v1/charger_type.h>
//#include <mt-plat/mtk_boot.h>
#include "MT5728_proprietary.h"
#include "MT5728_sha1.h"
#include "mt5728_wireless_driver_40w.h"
#define DEVICE_NAME "mt5728_iic"
#define DRIVER_FIRMWARE_VERSION "0.0.1"
#ifndef CONFIG_PRIZE_REVERE_CHARGING_MODE
#define CONFIG_PRIZE_REVERE_CHARGING_MODE
#endif
//prize add by lipengpeng 20220511 start
//#define TRUE 1
//#define FALSE 0
//prize add by lipengpeng 20220511 end
//#define MT5728_WIRELESS_TRX_MODE_SWITCH 1
//int wls_work_online = 0; //wireless charge working
//int reserse_charge_online = 0;
//int usb_otg_online = 0;
//int usbchip_otg_detect = 0;
// int MT5728_rt_mode_n = 0; //GPOD5,rxmode - 0
//volatile unsigned int AfcSendTimeout; //afc vout set time out
//volatile unsigned char AfcIntFlag;
volatile int rx_vout_max = 5000;
volatile int rx_iout_max = 1000;
//volatile int rx_iout_limit = 100;
#ifdef MT5728_USE_WAKELOCK
// static struct wake_lock mt5728_wls_wake_lock;
//static struct wakeup_source mt5728_wls_wake_lock;
#endif
//static int cur_last = 0;
static int powergood_err_cnt = 0;
volatile int setup_iout_start_cnt = 0;
volatile int reverse_timeout_cnt = 0;
volatile int current_change_interval_cnt = 0;
// static int mt5728_charging_otgin_flag = 0;
static int input_current_limit = 0;
#ifndef MT5728_CHIP_AUTO_AFC9V
//static volatile int vout_change_timecnt = 0;
#endif
//static volatile int current_reduce_flag = 0;
static int mt5728_vout_old;
static int mt5728_vrect_old;
static int mt5728_mtp_write_flag;
static volatile int mt5728_epp_ctrl_vout_flag;
//static int mt5728_ldo_on_flag;
//static struct charger_device *primary_charger;
//static volatile int mt5728_epp_ptpower;
static volatile int mt5728_ocp_reopen_tx_cnt;
static volatile int private_fskrecv_flag = 0;
static volatile int Private_packet_retrycnt = 0;
static int Private_state = 0; // add 20230717
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
static int mt5728_40w_init_done = 0;
#endif
static int mt5728_init_done = 0;
static volatile int mt5728_tx_cep_cnt_timeout = 0;
static volatile int mt5728_tx_cep_cnt_old = 0;
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
static struct charger_device *primary_charger;
static struct charger_device *primary_divider_chg;
#endif
int revere_mode=0;
EXPORT_SYMBOL(revere_mode);
#define OTP_WRITE_FLAG_ADDR 0x3E00 //In the middle of code area and trim area
static inline u16 crc_firmware(u16 poly1, u16 sed, u8 *buf, u32 n);
ssize_t Mt5728_get_vout(void);
static ssize_t Mt5728_set_vout(struct device* cd, struct device_attribute *attr, const char* buf, size_t len);
static ssize_t get_adapter(struct device* cd, struct device_attribute* attr, char* buf);
static ssize_t brushfirmware(struct device* dev, struct device_attribute* attr, const char* buf, size_t count);
static ssize_t updata_txFW(struct device* cd, struct device_attribute* attr, char* buf);
static ssize_t Mt5728_get_vrect(void);
int set_rx_ocp(uint16_t ocp);
int set_rx_vout(uint16_t vout);
int turn_on_5728_wpc_vdd(int en);
int turn_off_5728(int en);
typedef struct
{
unsigned char G;
s8 Offs;
} FodType;
FodType mt5728fod[8]={{250,127},{250,127},{250,127},{250,127},{250,127},{250,127},{250,127},{250,127}};
FodType mt5728fod_epp[8]={{250,127},{250,127},{250,127},{250,127},{250,127},{250,127},{250,127},{250,127}};
extern int wireless_charge_chage_current(void);
//prize add by lipengpeng 20220611 end
void fast_vfc(int vol);
//prize add by lipengpeng 20210831 start
//prize add by lipengpeng 20210416 start BPI_BUS4 GPIO90
//int test_gpio(int en);
int get_MT5728_status(void);
int get_MT5728_private_protocol_state(void);
//prize add by lipengpeng 20210416 start BPI_BUS4 GPIO90
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
//int turn_off_5725(int en);
//int turn_off_rever_5725(int en);
//int turn_on_rever_5725(int en);
int turn_on_otg_charge_mode(int en);
//int set_otg_gpio(int en);
//void mt_vbus_revere_on(void);
//extern void mt_vbus_revere_off(void);
//extern void mt_vbus_reverse_on_limited_current(void);
//extern void mt_vbus_reverse_off_limited_current(void);
#endif
struct MT5728_dev *mte;
//struct delayed_work MT5728_int_delayed_work;
typedef struct Pgm_Type {
u16 status;
u16 addr;
u16 length;
u16 cs;
u8 data[MTP_BLOCK_SIZE];
} Pgm_Type_t;
struct pinctrl* mt5728_pinctrl;
struct pinctrl_state *mt5728_rsv0_low, *mt5728_rsv0_high;
struct MT5728_func {
int (*read)(struct MT5728_dev* di, u16 reg, u8* val);
int (*write)(struct MT5728_dev* di, u16 reg, u8 val);
int (*read_buf)(struct MT5728_dev* di, u16 reg, u8* buf, u32 size);
int (*write_buf)(struct MT5728_dev* di, u16 reg, u8* buf, u32 size);
};
struct otg_wireless_ctl {
struct pinctrl *pinctrl_gpios;
struct pinctrl_state *pins_default;
struct pinctrl_state *charger_otg_off, *charger_otg_on,*wireless_5728_off,*wireless_5728_on,*charger_otg_mode_on, \
*charger_otg_mode_off,*test_gpio_on,*test_gpio_off,*mt5728_wpc_vdd_on,*mt5728_wpc_vdd_off;
bool gpio_otg_prepare;
};
enum wireless_charge_protocol {
PROTOCOL_UNKNOWN = 0,
BPP,
EPP,
AFC,
MAXIC_PRIVATE,
};
struct MT5728_dev {
char *name;
struct i2c_client* client;
struct device* dev;
struct regmap* regmap;
struct MT5728_func bus;
struct device_node *irq_nd; /* node */
struct delayed_work eint_work;
struct delayed_work add_current_work;
struct delayed_work charger_work;
struct delayed_work reverse_charge_work;
struct delayed_work fwcheck_work;
struct delayed_work mt5728_Private_packet_proc_work;
struct delayed_work mt5728_pp18_packet_send_work;
struct delayed_work mt5728_power_good_eint_work;
struct delayed_work mt5728_check_charge_state_work;
struct delayed_work mt5728_tx_enable_work;
struct delayed_work mt5728_tx_disable_work;
struct delayed_work mt5728_power_good_leave_check_work;
struct delayed_work mt5728_connect_over_time_work;
struct delayed_work mt5728_connect_check_work;
struct delayed_work mt5728_fw_update_work;
int irq_gpio;
int statu_gpio;
int fsk_status;
enum wireless_charge_protocol charge_protocol;
int wireless_max_power;
int input_current;
int charge_current;
int tx_count; //Enable TX function, write 0 for this value
struct otg_wireless_ctl otg_5728_ctl;
int otgen_gpio;
int one_pin_ctl;
int rx_power_cap;
int rx_efficiency;
int chipen_gpio; //sgm2541 en pn, active low, low:auto high:slave mode
int ldoctrl_gpio;
int test_r_gpio;
int usb_switch;
int power_good_gpio;
int power_good_irq;
struct work_struct power_good_eint_work;
struct workqueue_struct *power_good_eint_workqueue;
struct power_supply *psy;
int (*select_charging_current)(void);
atomic_t is_tx_mode;
int mt5728_ldo_on_flag;
int rxdetect_flag;
int rxremove_flag;
int private_protocol_state;
int force_swchg;
int disconnect_cnt;
int power_good_leave_double_check;
bool boot_complete;
bool wireless_connect_over_time;
bool chg_done;
struct power_supply *bms_psy;
};
#define REG_NONE_ACCESS 0
#define REG_RD_ACCESS (1 << 0)
#define REG_WR_ACCESS (1 << 1)
#define REG_BIT_ACCESS (1 << 2)
#define REG_MAX 0x0F
struct reg_attr {
const char* name;
u16 addr;
u8 flag;
};
enum REG_INDEX {
CHIPID = 0,
FWVERSION,
VOUT,
INT_FLAG,
INTCTLR,
VOUTSET,
VFC,
CMD,
INDEX_MAX,
};
static struct reg_attr reg_access[INDEX_MAX]={
[CHIPID] = { "CHIPID", REG_CHIPID, REG_RD_ACCESS },
[FWVERSION] = { "FWVERSION", REG_FW_VER, REG_RD_ACCESS },
[VOUT] = { "VOUT", REG_VOUT, REG_RD_ACCESS },
[INT_FLAG] = { "INT_FLAG", REG_INTFLAG, REG_RD_ACCESS },
[INTCTLR] = { "INTCLR", REG_INTCLR, REG_WR_ACCESS },
[VOUTSET] = { "VOUTSET", REG_VOUTSET, REG_RD_ACCESS | REG_WR_ACCESS },
[VFC] = { "VFC", REG_VFC, REG_RD_ACCESS | REG_WR_ACCESS },
[CMD] = { "CMD", REG_CMD, REG_RD_ACCESS | REG_WR_ACCESS | REG_BIT_ACCESS },
};
static u32 SizeofPkt(u8 hdr) {
if (hdr < 0x20)
return 1;
if (hdr < 0x80)
return (2 + ((hdr - 0x20) >> 4));
if (hdr < 0xe0)
return (8 + ((hdr - 0x80) >> 3));
return (20 + ((hdr - 0xe0) >> 2));
}
/*
int wireless_charge_chage_current(void)
{
return 0;
}
*/
static int MT5728_read(struct MT5728_dev* di, u16 reg, u8* val) {
unsigned int temp;
int rc;
rc = regmap_read(di->regmap, reg, &temp);
if (rc >= 0)
*val = (u8)temp;
return rc;
}
static int MT5728_write(struct MT5728_dev* di, u16 reg, u8 val) {
int rc = 0;
rc = regmap_write(di->regmap, reg, val);
if (rc < 0)
dev_err(di->dev, "MT5728 write error: %d\n", rc);
return rc;
}
static int MT5728_read_buffer(struct MT5728_dev* di, u16 reg, u8* buf, u32 size) {
return regmap_bulk_read(di->regmap, reg, buf, size);
}
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
int mt5728_read(u16 reg, u8* buf, u32 size)
{
return MT5728_read_buffer(mte,reg,buf,size);
}
#endif
static int MT5728_write_buffer(struct MT5728_dev* di, u16 reg, u8* buf, u32 size) {
int rc = 0;
rc = regmap_bulk_write(di->regmap, reg, buf, size);
return rc;
}
static void mt5728_sram_write(u32 addr, u8 *data,u32 len) {
u32 offset,length,size;
offset = 0;
length = 0;
size = len;
pr_info("[%s] Length to write:%d\n",__func__, len);
while(size > 0) {
if(size > SRAM_PAGE_SIZE) {
length = SRAM_PAGE_SIZE;
} else {
length = size;
}
pr_info("[%s] Length of this write :%d\n",__func__,length);
MT5728_write_buffer(mte, addr + offset ,data+offset, length);
size -= length;
offset += length;
msleep(2);
}
pr_info("[%s] Write completion\n",__func__);
}
static void mt5728_run_pgm_fw(void) {
vuc val;
//wdg_disable
val.value = MT5728_WDG_DISABLE;
MT5728_write_buffer(mte, MT5728_PMU_WDGEN_REG, val.ptr, 2);
MT5728_write_buffer(mte, MT5728_PMU_WDGEN_REG, val.ptr, 2);
MT5728_write_buffer(mte, MT5728_PMU_WDGEN_REG, val.ptr, 2);
val.value = MT5728_WDT_INTFALG;
MT5728_write_buffer(mte, MT5728_PMU_FLAG_REG, val.ptr, 2);
val.value = MT5728_KEY;
MT5728_write_buffer(mte, MT5728_SYS_KEY_REG, val.ptr, 2);
val.value = 0X08;
MT5728_write_buffer(mte, MT5728_CODE_REMAP_REG, val.ptr, 2);
val.value = 0x0FFF;
MT5728_write_buffer(mte, MT5728_SRAM_REMAP_REG, val.ptr, 2);
msleep(50);
//sram_write
mt5728_sram_write(0x1800,(u8 *)mt5728_pgm_bin,sizeof(mt5728_pgm_bin));
//sys_run
msleep(50);
val.value = MT5728_KEY;
MT5728_write_buffer(mte, MT5728_SYS_KEY_REG, val.ptr, 2);
val.value = MT5728_M0_RESET;
MT5728_write_buffer(mte, MT5728_M0_CTRL_REG, val.ptr, 2);
msleep(50);
pr_info("[%s] finish \n",__func__);
}
static u8 mt5728_mtp_read(u32 addr, u8 * buf , u32 size, u8 mode) {
u32 length ,i,status,times;
vuc val;
Pgm_Type_t pgm;
pr_info("[%s] parameter size :%d\n",__func__,size);
length = (size+(MTP_BLOCK_SIZE-1))/MTP_BLOCK_SIZE*MTP_BLOCK_SIZE;
mt5728_run_pgm_fw();
pr_info("[%s] Calculate the length to read:%d\n",__func__,length);
for (i = 0; i < length/MTP_BLOCK_SIZE; ++i) {
pgm.length = MTP_BLOCK_SIZE;
pgm.addr = addr+i*MTP_BLOCK_SIZE;
pgm.status = PGM_STATUS_READY;
val.value = pgm.status;
MT5728_write_buffer(mte,PGM_STATUS_ADDR,val.ptr,2);
val.value = pgm.addr;
MT5728_write_buffer(mte,PGM_ADDR_ADDR,val.ptr,2);
val.value = pgm.length;
MT5728_write_buffer(mte,PGM_LENGTH_ADDR,val.ptr,2);
val.value = PGM_STATUS_READ;
MT5728_write_buffer(mte,PGM_STATUS_ADDR,val.ptr,2);
msleep(50);
MT5728_read_buffer(mte, PGM_STATUS_ADDR, val.ptr, 2);
status = val.ptr[0];
times = 0;
while(status == PGM_STATUS_READ) {
msleep(50);
MT5728_read_buffer(mte, PGM_STATUS_ADDR, val.ptr, 2);
pr_info("[%s] Program reading",__func__);
status = val.ptr[0];
times+=1;
if (times>100) {
pr_err("[%s] error! Read OTP TImeout\n",__func__);
return FALSE;
}
}
if (status == PGM_STATUS_PROGOK) {
pr_info("[%s] PGM_STATUS_PROGOK\n",__func__);
MT5728_read_buffer(mte, PGM_DATA_ADDR, &buf[MTP_BLOCK_SIZE*i], MTP_BLOCK_SIZE);
} else {
pr_err("[%s] OtpRead error , status = 0x%02x\n",__func__,status);
return FALSE;
}
if (mode == TRUE) {
/* code */
}
}
return TRUE;
}
static u8 mt5728_mtp_write(u32 addr, u8 * buf , u32 len) {
u32 offset;
u32 write_size ,status,times;
u32 write_retrycnt;
s32 size;
int i;
vuc val;
Pgm_Type_t pgm;
size = len;
offset = 0;
write_size = 0;
pr_info("[%s] Size to write:%d\n",__func__,size);
mt5728_run_pgm_fw();
write_retrycnt = 8;
while(size>0) {
if (size>MTP_BLOCK_SIZE) {
pgm.length = MTP_BLOCK_SIZE;
write_size = MTP_BLOCK_SIZE;
} else {
pgm.length = size;
write_size = size;
}
pgm.addr = addr+offset;
pgm.cs = pgm.addr;
pgm.status = PGM_STATUS_READY;
for (i = 0; i < pgm.length; ++i) {
pgm.data[i] = buf[offset + i];
pgm.cs += pgm.data[i];
}
pgm.cs+=pgm.length;
val.value = pgm.status;
MT5728_write_buffer(mte,PGM_STATUS_ADDR,val.ptr,2);
val.value = pgm.addr;
MT5728_write_buffer(mte,PGM_ADDR_ADDR,val.ptr,2);
val.value = pgm.length;
MT5728_write_buffer(mte,PGM_LENGTH_ADDR,val.ptr,2);
val.value = pgm.cs;
MT5728_write_buffer(mte,PGM_CHECKSUM_ADDR,val.ptr,2);
MT5728_write_buffer(mte, PGM_DATA_ADDR, pgm.data, pgm.length);
val.value = PGM_STATUS_WMTP;
MT5728_write_buffer(mte,PGM_STATUS_ADDR,val.ptr,2);
msleep(50);
MT5728_read_buffer(mte, PGM_STATUS_ADDR, val.ptr, 2);
status = val.ptr[0];
times = 0;
while(status == PGM_STATUS_WMTP) {
msleep(50);
MT5728_read_buffer(mte, PGM_STATUS_ADDR, val.ptr, 2);
status = val.ptr[0];
pr_info("[%s] Program writing\n",__func__);
times+=1;
if (times > 100) {
pr_err("[%s] Program write timeout\n",__func__);
return FALSE;
}
}
if (status == PGM_STATUS_PROGOK) {
size-=write_size;
offset+=write_size;
pr_info("[%s] PGM_STATUS_PROGOK\n",__func__);
} else if (status == PGM_STATUS_ERRCS) {
if (write_retrycnt > 0) {
write_retrycnt--;
pr_err("[%s] ERRCS write_retrycnt:%d\n",__func__,write_retrycnt);
continue;
} else {
pr_err("[%s] PGM_STATUS_ERRCS\n",__func__);
return FALSE;
}
} else if (status == PGM_STATUS_ERRPGM) {
if (write_retrycnt > 0) {
write_retrycnt--;
pr_err("[%s] ERRPGM write_retrycnt:%d\n",__func__,write_retrycnt);
continue;
} else {
pr_err("[%s] PGM_STATUS_ERRPGM\n",__func__);
return FALSE;
}
} else {
if (write_retrycnt > 0) {
write_retrycnt--;
pr_err("[%s] NUKNOWN write_retrycnt:%d\n",__func__,write_retrycnt);
continue;
} else {
pr_err("[%s] PGM_STATUS_NUKNOWN \n",__func__);
return FALSE;
}
}
}
return TRUE;
}
static u8 mt5728_mtp_write_check(u32 flagaddr,u16 crc) {
u8 i;
u8 otpwrite_flagdata[4];
u8 *otpwrite_flagread;
otpwrite_flagread = kmalloc(1064, GFP_KERNEL);
otpwrite_flagdata[0] = crc % 256;
otpwrite_flagdata[1] = crc / 256;
otpwrite_flagdata[2] = crc % 256;
otpwrite_flagdata[3] = crc / 256;
mt5728_mtp_read(flagaddr, otpwrite_flagread,4,1);
for (i = 0; i < 4; ++i) {
if (otpwrite_flagread[i] != otpwrite_flagdata[i]) {
pr_info("[%s] MT5728 MTP Flag not written: %d\n",__func__,i);
return FALSE;
}
}
printk("[%s] MT5728 MTP Flag has been written",__func__);
kfree(otpwrite_flagread);
return TRUE;
}
void mt5728_write_mtpok_flag(u32 flagaddr,u16 crc) {
}
static u8 mt5728_mtp_verify(u32 addr,u8 * data,u32 len) {
vuc val;
int waitTimeOutCnt;
int status;
u16 crcvlaue;
u16 crcvlaue_chip;
Pgm_Type_t pgm;
// crcvlaue = crc_ccitt(0xFFFF,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin));
crcvlaue = crc_firmware(0x1021, 0xFFFF, (u8*)MT5728_mtp_bin, sizeof(MT5728_mtp_bin)) & 0xffff;
val.value = 0;
MT5728_write_buffer(mte,PGM_ADDR_ADDR,val.ptr,2);
val.value = sizeof(MT5728_mtp_bin);
MT5728_write_buffer(mte,PGM_LENGTH_ADDR,val.ptr,2);
pgm.cs = crcvlaue;
val.value = pgm.cs;
MT5728_write_buffer(mte,PGM_CHECKSUM_ADDR,val.ptr,2);
val.value = (1 << 6);
MT5728_write_buffer(mte,PGM_STATUS_ADDR,val.ptr,2);
waitTimeOutCnt = 100;
while(waitTimeOutCnt--) {
MT5728_read_buffer(mte, PGM_STATUS_ADDR, val.ptr, 2);
status = val.ptr[0] | (val.ptr[1] << 8);
if (status & (1 << 7)) {
MT5728_read_buffer(mte, PGM_DATA_ADDR, val.ptr, 2);
crcvlaue_chip = val.value;
printk(KERN_ALERT "[%s] mt5728_mtp_verify error,crcvlaue_chip:%x,crcvlaue:%x",__func__,crcvlaue_chip,crcvlaue);
return FALSE;
}
//VERIFYOK
if (status & (1 << 8)) {
MT5728_read_buffer(mte, PGM_DATA_ADDR, val.ptr, 2);
crcvlaue_chip = val.value;
g_crcvalue = crcvlaue_chip;
printk(KERN_ALERT "[%s] mt5728_mtp_verify success,crcvlaue_chip:%x,crcvlaue:%x",__func__,crcvlaue_chip,crcvlaue);
return TRUE;
}
msleep(60);
}/**/
printk(KERN_ALERT "[%s] TimeOut cal_crc :0x%04x\n",__func__,crcvlaue);
return FALSE;
}
static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
{
return (crc >> 8) ^ mt5728_crc_ccitt_table[(crc ^ c) & 0xff];
}
static u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
{
while (len--)
crc = crc_ccitt_byte(crc, *buffer++);
return crc;
}
static inline u16 crc_firmware(u16 poly1, u16 sed, u8 *buf, u32 n) {
u32 i = 0;
u32 j = 0;
u16 poly = 0x1021;
u16 crc = 0xffff;
// u32 addr = 0x20000070;
for (j = 0; j < n; j+=2) {
crc ^= (buf[j+1] << 8);
for (i = 0;i < 8; i++) {
crc = (crc & 0x8000) ? (((crc << 1) & 0xffff) ^ poly) : (crc << 1);
}
/* *(u8*)addr = buf[j+1]; */
/* addr ++; */
crc ^= (buf[j] << 8);
for (i = 0;i < 8; i++) {
crc = (crc & 0x8000) ? (((crc << 1) & 0xffff) ^ poly) : (crc << 1);
}
/* *(u8*)addr = buf[j]; */
/* addr ++; */
/* *(u32*)0x200000a0 = addr; */
}
return crc;
}
/*
Send proprietary packet to Tx
Step 1: write data into REG_PPP
Step 2: write REG_CMD
*/
void MT5728_send_ppp(PktType *pkt) {
vuc val;
MT5728_write_buffer(mte, REG_PPP, (u8 *)pkt, SizeofPkt(pkt->header)+1);
mte->fsk_status = FSK_WAITTING;
val.value = SEND_PPP;
MT5728_write_buffer(mte, REG_CMD, val.ptr, 2);
msleep(5);
}
EXPORT_SYMBOL(MT5728_send_ppp);
void mt5728_send_ask_key(void)
{
PktType eptpkt;
eptpkt.header = PP18;
eptpkt.msg_pakt.cmd = 0x2b;
MT5728_send_ppp(&eptpkt);
pr_err("[%s]++\n",__func__);
}
EXPORT_SYMBOL(mt5728_send_ask_key);
int Get_adaptertype(void){
PktType eptpkt;
int count = 0;
u8 fsk_msg[10];
eptpkt.header = PP18;
eptpkt.msg_pakt.cmd = CMD_ADAPTER_TYPE;
MT5728_send_ppp(&eptpkt);
while(mte->fsk_status == FSK_WAITTING){
msleep(20);
if((count++) > 50 ){
pr_err("[%s] AP system judgement:FSK receive timeout \n",__func__);
return (-1);
}
}
if(mte->fsk_status == FSK_FAILED){
pr_err("[%s] Wireless charging system judgement:FSK receive timeout \n",__func__);
return (-1);
}
if(mte->fsk_status == FSK_SUCCESS){
MT5728_read_buffer(mte,REG_BC,fsk_msg,10);
pr_info("[%s] Information received : 0x%02x 0x%02x 0x%02x \n",__func__,fsk_msg[0],fsk_msg[1],fsk_msg[2]);
}
return fsk_msg[2];
}
static ssize_t get_reg(struct device* cd, struct device_attribute* attr, char* buf) {
vuc val;
ssize_t len = 0;
int i = 0;
for (i = 0; i < INDEX_MAX; i++) {
if (reg_access[i].flag & REG_RD_ACCESS) {
MT5728_read_buffer(mte, reg_access[i].addr, val.ptr, 2);
len += snprintf(buf + len, PAGE_SIZE - len, "reg:%s 0x%04x=0x%04x,%d\n", reg_access[i].name, reg_access[i].addr, val.value,val.value);
}
}
return len;
}
static ssize_t set_reg(struct device* cd, struct device_attribute* attr, const char* buf, size_t len) {
unsigned int databuf[2];
vuc val;
u8 tmp[2];
u16 regdata;
int i = 0;
int ret = 0;
ret = sscanf(buf, "%x %x", &databuf[0], &databuf[1]);
if (2 == ret) {
for (i = 0; i < INDEX_MAX; i++) {
if (databuf[0] == reg_access[i].addr) {
if (reg_access[i].flag & REG_WR_ACCESS) {
// val.ptr[0] = (databuf[1] & 0xff00) >> 8;
val.value = databuf[1];
// val.ptr[1] = databuf[1] & 0x00ff; //big endian
if (reg_access[i].flag & REG_BIT_ACCESS) {
MT5728_read_buffer(mte, databuf[0], tmp, 2);
regdata = tmp[0] << 8 | tmp[1];
val.value |= regdata;
pr_info("get reg: 0x%04x set reg: 0x%04x \n", regdata, val.value);
MT5728_write_buffer(mte, databuf[0], val.ptr, 2);
} else {
pr_info("Set reg : [0x%04x] 0x%x \n", databuf[0], val.value);
MT5728_write_buffer(mte, databuf[0], val.ptr, 2);
}
}
break;
}
}
}else{
pr_info("Error \n");
}
return len;
}
static ssize_t fast_charging_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
vuc val;
int error;
unsigned int a;
error = kstrtouint(buf, 10, &a);
val.value = (unsigned short)a;
if (error)
return error;
if ((val.value < 0) || (val.value > 20000)) {
pr_info("[%s] MT5728 Parameter error\n",__func__);
return count;
}
fast_vfc(val.value);
return count;
}
static ssize_t get_adapter(struct device* cd, struct device_attribute* attr, char* buf) {
ssize_t len = 0;
int rc;
rc = Get_adaptertype();
if(rc == (-1)){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Failed to read adapter type\n", __func__);
}else if(rc == ADAPTER_NONE ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : Unknown\n", __func__);
}else if(rc == ADAPTER_SDP ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : SDP\n", __func__);
}else if(rc == ADAPTER_CDP ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : CDP\n", __func__);
}else if(rc == ADAPTER_DCP ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : DCP\n", __func__);
}else if(rc == ADAPTER_QC20 ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : QC2.0\n", __func__);
}else if(rc == ADAPTER_QC30 ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : QC3.0\n", __func__);
}else if(rc == ADAPTER_PD ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : PD\n", __func__);
}else if(rc == ADAPTER_FCP ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : FCP\n", __func__);
}else if(rc == ADAPTER_SCP ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : SCP\n", __func__);
}else if(rc == ADAPTER_DCS ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : DC source\n", __func__);
}else if(rc == ADAPTER_AFC ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : AFC\n", __func__);
}else if(rc == ADAPTER_PDPPS ){
len += snprintf(buf + len, PAGE_SIZE - len, "[%s] Adapter type : PD PPS\n", __func__);
}
return len;
}
static ssize_t brushfirmware(struct device* dev, struct device_attribute* attr, const char* buf, size_t count) {
int error;
int mt5728VoutTemp;
unsigned int pter;
error = kstrtouint(buf, 10, &pter);
mt5728_mtp_write_flag = 1;
mt5728VoutTemp = Mt5728_get_vout();
if (mt5728VoutTemp < 0) {
//mt5728_ap_open_otg_boost(true);
}
msleep(1000); //Wait for Vout voltage to stabilize
if(pter == 1){
printk(KERN_ALERT "[%s] brush MTP program\n",__func__);
if(mt5728_mtp_write(0x0000,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin))){
printk(KERN_ALERT "[%s] Write complete, start verification \n",__func__);
if (mt5728_mtp_verify(0x0000,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin))) {
printk(KERN_ALERT "[%s] mt5728_mtp_verify OK \n",__func__);
} else {
printk(KERN_ALERT "[%s] mt5728_mtp_verify check program failed \n",__func__);
}
}
}else if(pter == 2){
u16 crcvlaue;
crcvlaue = crc_ccitt(0xFFFF,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin));
printk(KERN_ALERT "[%s] cal_crc :0x%04x\n",__func__,crcvlaue);
if(mt5728_mtp_write_check(MTP_WRITE_FLAG_ADDR,crcvlaue)==TRUE){
printk(KERN_ALERT "[%s] mt5728_mtp_write exit \n",__func__);
} else {
if(mt5728_mtp_write(0x0000,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin))){
printk(KERN_ALERT "[%s] Write complete, start verification \n",__func__);
if (mt5728_mtp_verify(0x0000,(u8 *)MT5728_mtp_bin,sizeof (MT5728_mtp_bin))) {
printk(KERN_ALERT "[%s] mt5728_mtp_verify OK \n",__func__);
mt5728_write_mtpok_flag(MTP_WRITE_FLAG_ADDR,crcvlaue);
printk(KERN_ALERT "[%s] MT5728_write_mtp_flag \n",__func__);
} else {
printk(KERN_ALERT "[%s] mt5728_mtp_verify check program failed \n",__func__);
}
}
}
} else if(pter == 3)
{
schedule_delayed_work(&mte->fwcheck_work, msecs_to_jiffies(100));
}
if (mt5728VoutTemp < 0) {
//mt5728_ap_open_otg_boost(false);
}
printk(KERN_ALERT "[%s] Exit this operation \n",__func__);
mt5728_mtp_write_flag = 0;
return count;
}
static DEVICE_ATTR(fast_charging, S_IRUGO | S_IWUSR, NULL, fast_charging_store);
static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, get_reg, set_reg);
static DEVICE_ATTR(adapter_type,S_IRUGO,get_adapter,NULL);
static DEVICE_ATTR(brushFW,S_IRUGO | S_IWUSR,NULL,brushfirmware);
static DEVICE_ATTR(TxFirmware,S_IRUGO | S_IWUSR,updata_txFW,NULL);
static DEVICE_ATTR(epp_set_vout, S_IRUGO | S_IWUSR, NULL, Mt5728_set_vout);
void fast_vfc(int vol) {
vuc val;
val.value = vol;
MT5728_write_buffer(mte, REG_VFC, val.ptr, 2);
val.value = FAST_CHARGE;
MT5728_write_buffer(mte, REG_CMD, val.ptr, 2);
pr_info("%s,write reg_cmd : 0x%04x,\n", __func__, val.value);
}
static void download_txSRAM_code(void) {
vuc val;
val.value = MT5728_WDG_DISABLE;
MT5728_write_buffer(mte, MT5728_PMU_WDGEN_REG, val.ptr, 2);
MT5728_write_buffer(mte, MT5728_PMU_WDGEN_REG, val.ptr, 2);
MT5728_write_buffer(mte, MT5728_PMU_WDGEN_REG, val.ptr, 2);
val.value = MT5728_WDT_INTFALG;
MT5728_write_buffer(mte,MT5728_PMU_FLAG_REG,val.ptr,2);
val.value = MT5728_KEY;
MT5728_write_buffer(mte,MT5728_SYS_KEY_REG,val.ptr,2);
val.value = MT5728_M0_HOLD | LBIT(9);
MT5728_write_buffer(mte,MT5728_M0_CTRL_REG,val.ptr,2);
msleep(50);
mt5728_sram_write(0x800,(u8 *)MT572x_TxSRAM_bin,sizeof(MT572x_TxSRAM_bin));
val.value = 0x02;
MT5728_write_buffer(mte,MT5728_CODE_REMAP_REG,val.ptr,2);
val.value = 0xff0f;
MT5728_write_buffer(mte,MT5728_SRAM_REMAP_REG,val.ptr,2);
val.value = MT5728_KEY;
MT5728_write_buffer(mte,MT5728_SYS_KEY_REG,val.ptr,2);
val.value = MT5728_M0_RESET ;
MT5728_write_buffer(mte,MT5728_M0_CTRL_REG,val.ptr,2);
msleep(50);
printk(KERN_ALERT "[%s] finish\n",__func__);
}
static ssize_t updata_txFW(struct device* cd, struct device_attribute* attr, char* buf) {
ssize_t len = 0;
download_txSRAM_code();
return len;
}
void fastcharge_afc(void) {
vuc val;
vuc temp, fclr, scmd;
scmd.value = 0;
MT5728_read_buffer(mte, REG_INTFLAG, val.ptr, 2);
fclr.value = FAST_CHARGE;
if (val.value & INT_AFC_SUPPORT) {
pr_info("MT5728 %s ,version 0.1 Tx support samsung_afc\n", __func__);
temp.value = 9000;
MT5728_write_buffer(mte, REG_VFC, temp.ptr, 2);
scmd.value |= FAST_CHARGE;
scmd.value |= CLEAR_INT;
MT5728_write_buffer(mte, REG_INTCLR, fclr.ptr, 2);
pr_info("%s,version 0.1 write reg_clr : 0x%04x,\n", __func__, fclr.value);
MT5728_write_buffer(mte, REG_CMD, scmd.ptr, 2);
pr_info("%s,version 0.1 write reg_cmd : 0x%04x,\n", __func__, scmd.value);
}
}
//prize add by lipengpeng 20210308 start
int set_usb_switch(int en)
{
if(gpio_is_valid(mte->usb_switch))
{
if(en)
{
gpio_direction_output(mte->usb_switch,1);
}
else
{
gpio_direction_output(mte->usb_switch,0);
}
}
return 0;
}
/*
static ssize_t usb_switch_show(struct device *dev, struct device_attribute *attr,char *buf)
{
return sprintf(buf, "%d\n", gpio_get_value(mte->usb_switch));
}
static ssize_t usb_switch_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
{
int error;
unsigned int temp;
error = kstrtouint(buf, 10, &temp);
if (error)
return error;
pr_err("gezi---%s-----%d\n",__func__,temp);
set_usb_switch(temp);
return count;
}
static DEVICE_ATTR(usb_switch, 0664, usb_switch_show, usb_switch_store);
*/
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
static ssize_t gettx_flag_show(struct device *dev, struct device_attribute *attr,char *buf)
{
//if(TXupon_coil==1){
return sprintf(buf, "%d", atomic_read(&mte->is_tx_mode));
//}else{
// return sprintf(buf, "%d", 0);
//}
}
static DEVICE_ATTR(gettxflag, 0644, gettx_flag_show, NULL);
/*static ssize_t disable_tx_show(struct device *dev, struct device_attribute *attr,char *buf)
{
struct i2c_client *client = to_i2c_client(dev);
struct MT5728_dev *chip = i2c_get_clientdata(client);
mutex_lock(&chip->ops_mutex);
gpio_direction_output(chip->trxset_gpio,0);
//charger_dev_enable_otg(g_info->primary_charger, false);
//enable_boost_polling(false);
mt_vbus_off();
gpio_direction_output(chip->otgen_gpio,0);
atomic_set(&mte->is_tx_mode,0);
mutex_unlock(&chip->ops_mutex);
printk(KERN_INFO"mt5728 disable_tx\n");
return sprintf(buf, "%d", 1);
}
static DEVICE_ATTR(disabletx, 0644, disable_tx_show, NULL);
*/
static int battery_get_vbus(void)
{
#if IS_ENABLED(CONFIG_READ_PMIC_VBUS)
union power_supply_propval prop;
if(IS_ERR_OR_NULL(mte->bms_psy)){
mte->bms_psy = power_supply_get_by_name("battery");
if(IS_ERR_OR_NULL(mte->bms_psy)){
pr_err("gezi get bms_psy error\n");
//*tbat = 50;
return 0;
}
goto to;
}
to:
power_supply_get_property(mte->bms_psy,POWER_SUPPLY_PROP_INPUT_VOLTAGE_LIMIT, &prop);
return prop.intval;
#else
return 0;
#endif
}
static void mt5728_reset(void)
{
pr_info("++%s\n",__func__);
turn_off_5728(1);
msleep(600);
turn_off_5728(0);
}
static int mt_vbus_revere_on(int on)
{
int retry_cnt = 10,vbus = 0;
if (!primary_charger) {
primary_charger = get_charger_by_name("primary_chg");
if (!primary_charger) {
pr_info("%s: get primary_chg device failed\n", __func__);
return -ENODEV;
}
}
pr_err("gezi:%s-----%d\n",__func__,on);
if(on){
while(retry_cnt > 0)
{
if(!revere_mode){
charger_dev_enable_otg(primary_charger, false);
pr_err("gezi:%s---exit0 revere_mode--%d,return...\n",__func__,revere_mode);
break;
}
pr_err("gezi:%s---charger_dev_enable_otg start,retry_cnt:%d\n",__func__,retry_cnt);
charger_dev_enable_otg(primary_charger, true);
charger_dev_set_boost_current_limit(primary_charger, 1800000);
msleep(600);
vbus = battery_get_vbus();
if(vbus > 4000){
pr_err("gezi:%s---charger_dev_enable_otg--ok!,vbus:%d,retry_cnt:%d\n",__func__,vbus,retry_cnt);
break;
}
else{
pr_err("gezi:[mt5728 %s]primary_chg output:%d v err!!,retry\n",__func__,vbus);
charger_dev_enable_otg(primary_charger, false);
if(retry_cnt <= 3){
mt5728_reset();
}
retry_cnt--;
msleep(100);
}
}
} else{
charger_dev_enable_otg(primary_charger, false);
}
if(!revere_mode){
charger_dev_enable_otg(primary_charger, false);
pr_err("gezi:%s---exit1 revere_mode--%d,return...\n",__func__,revere_mode);
}
return 0;
}
static int mt_vbus_revere_off(void)
{
if (!primary_charger) {
primary_charger = get_charger_by_name("primary_chg");
if (!primary_charger) {
pr_info("%s: get primary_chg device failed\n", __func__);
return -ENODEV;
}
}
pr_err("gezi:%s-----\n",__func__);
charger_dev_enable_otg(primary_charger, false);
return 0;
}
static int mtk_set_sc8571_otg(int on)
{
if (!primary_divider_chg) {
primary_divider_chg = get_charger_by_name("primary_dvchg");
if (!primary_divider_chg) {
pr_info("%s: get primary_divider_chg device failed\n", __func__);
return -ENODEV;
}
}
if(on){
charger_dev_enable_otg(primary_divider_chg, true);
} else{
charger_dev_enable_otg(primary_divider_chg, false);
}
return 0;
}
static struct delayed_work mt5728_everse_charge_start_ping_work;
static bool is_ping = false;
//static bool is_reverse_charge_work_running = false;
static void mt5728_reverse_charge_start_ping_work_func(struct work_struct* work)
{
vuc txinit;
MT5728_read_buffer(mte,REG_STABILITY,txinit.ptr,2);
pr_err("[%s] TX val = 0x%x\n",__func__,txinit.value);
if(txinit.value == 0x5555){
txinit.value = 0x6666;
MT5728_write_buffer(mte,REG_STABILITY,txinit.ptr,2);
pr_err("[%s] TX starts working\n",__func__);
mte->rxdetect_flag = 0;
mte->rxremove_flag = 0;
reverse_timeout_cnt = 0;
mt5728_tx_cep_cnt_timeout = 0;
//if(!is_reverse_charge_work_running){
// is_reverse_charge_work_running = true;
schedule_delayed_work(&mte->reverse_charge_work, msecs_to_jiffies(100));
//}
}
is_ping = false;
}
static void mt5728_tx_mode_start_ping(bool on)
{
if(on == is_ping){
pr_err("[%s] already open:%d\n",__func__,is_ping);
return;
}
if(on){
INIT_DELAYED_WORK(&mt5728_everse_charge_start_ping_work, mt5728_reverse_charge_start_ping_work_func);
schedule_delayed_work(&mt5728_everse_charge_start_ping_work,msecs_to_jiffies(1000));
}
is_ping = on;
}
static bool start_fw_up = false;
u16 g_crcvalue = 0;
u16 g_fw_ver = 0;
static ssize_t fw_ver_show(struct device *dev, struct device_attribute *attr,char *buf)
{
return sprintf(buf, "%x", g_fw_ver);//atomic_read(&mte->is_tx_mode);// prize add by lpp 20210308
}
static DEVICE_ATTR(fw_ver, 0444, fw_ver_show, NULL);
static ssize_t crcvalue_show(struct device *dev, struct device_attribute *attr,char *buf)
{
pr_err("MT5728 g_crcvalue : 0x%x\n",g_crcvalue);
return sprintf(buf, "%x", g_crcvalue);
}
static DEVICE_ATTR(crcvalue, 0444, crcvalue_show, NULL);
static void mt5728_start_fw_update(void)
{
u16 crcvlaue = 0;
u8 fw[2] = {0};
if(start_fw_up){
pr_err("gezi---%s-----already starting\n",__func__);
return;
}
pr_err("gezi---%s-----start\n",__func__);
//turn_on_otg_charge_mode(1); //GPIO109---->high //prize add by lipengpeng 20210408 GPIO ---> low.
atomic_set(&mte->is_tx_mode,1);
revere_mode=1;
start_fw_up = true;
mt_vbus_revere_on(1);
mtk_set_sc8571_otg(1);
msleep(1500);
crcvlaue = crc_ccitt(0xFFFF,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin));
printk(KERN_ALERT "[%s] cal_crc :0x%04x\n",__func__,crcvlaue);
if(mt5728_mtp_write_check(MTP_WRITE_FLAG_ADDR,crcvlaue)==TRUE){
printk(KERN_ALERT "[%s] mt5728_mtp_write exit \n",__func__);
} else {
if(mt5728_mtp_write(0x0000,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin))){
printk(KERN_ALERT "[%s] Write complete, start verification \n",__func__);
if (mt5728_mtp_verify(0x0000,(u8 *)MT5728_mtp_bin,sizeof (MT5728_mtp_bin))) {
printk(KERN_ALERT "[%s] mt5728_mtp_verify OK \n",__func__);
mt5728_write_mtpok_flag(MTP_WRITE_FLAG_ADDR,crcvlaue);
MT5728_read_buffer(mte, REG_FW_VER, fw, 2);
g_fw_ver = (fw[0] << 8) + fw[1];
pr_err("MT5728 fw_version_in_chip : 0x%x\n",g_fw_ver);
printk(KERN_ALERT "[%s] MT5728_write_mtp_flag \n",__func__);
} else {
printk(KERN_ALERT "[%s] mt5728_mtp_verify check program failed \n",__func__);
}
}
else{
printk(KERN_ALERT "[%s] mt5728_mtp_write error\n",__func__);
}
}
mt_vbus_revere_off();
mtk_set_sc8571_otg(0);
turn_on_otg_charge_mode(0);//GPIO109--->low
atomic_set(&mte->is_tx_mode,0);
revere_mode=0;
start_fw_up = false;
pr_err("gezi---%s-----ok\n",__func__);
}
static void mt5728_fw_update_work_func(struct work_struct* work)
{
pr_err("gezi---%s-----\n",__func__);
mt5728_start_fw_update();
}
static ssize_t fw_update_show(struct device *dev, struct device_attribute *attr,char *buf)
{
return sprintf(buf, "%d", start_fw_up);
}
static ssize_t fw_update_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
{
int error;
unsigned int temp;
error = kstrtouint(buf, 10, &temp);
if (error)
return error;
pr_err("gezi---%s---up state:%d--\n",__func__,start_fw_up);
if(start_fw_up){
return count;
}
schedule_delayed_work(&mte->mt5728_fw_update_work,msecs_to_jiffies(10));
return count;
}
static DEVICE_ATTR(fw_update, 0664, fw_update_show, fw_update_store);
void mt5728_tx_modestability_start(void) {
vuc val;
val.value = 0x6666;
MT5728_write_buffer(mte, 0x64, val.ptr, 2);
}
void mt5728_soft_reset(void)
{
vuc val;
printk(KERN_ALERT "[%s] start\n", __func__);
val.value = MT5728_KEY;
MT5728_write_buffer(mte, MT5728_SYS_KEY_REG, val.ptr, 1);
val.ptr[0] = MT5728_M0_RESET;
MT5728_write_buffer(mte, MT5728_M0_CTRL_REG, val.ptr, 1);
msleep(100);
}
static void mt5728_tx_enable_work_func(struct work_struct* work)
{
if(!revere_mode){
pr_err("[%s]revere_mode off...return\n",__func__);
}
printk(KERN_INFO"mt5728 000 enable tx\n");
mte->tx_count=0;
mt5728_ocp_reopen_tx_cnt = 3;
reverse_timeout_cnt = 0;
cancel_delayed_work(&mte->mt5728_Private_packet_proc_work);
cancel_delayed_work(&mte->mt5728_pp18_packet_send_work);
turn_on_otg_charge_mode(1); //GPIO109---->high //prize add by lipengpeng 20210408 GPIO ---> low.
printk(KERN_INFO"mt5728 222 enable tx\n");
printk(KERN_INFO"mt5728 333 enable tx\n");
mt_vbus_revere_on(1);// open vbus
mtk_set_sc8571_otg(1);
msleep(100);
mt5728_soft_reset();
mt5728_tx_mode_start_ping(true);
printk(KERN_INFO"mt5728 444 enable tx\n");
}
static void mt5728_tx_disable_work_func(struct work_struct* work)
{
if(!revere_mode){
pr_err("[%s]revere_mode on...return\n",__func__);
}
printk(KERN_INFO"mt5728 000 disable tx\n");
mte->tx_count=0;
mt_vbus_revere_off();
mtk_set_sc8571_otg(0);
turn_on_otg_charge_mode(0);//GPIO109--->low
atomic_set(&mte->is_tx_mode,0);
if(is_ping){
cancel_delayed_work(&mt5728_everse_charge_start_ping_work);
is_ping = false;
}
cancel_delayed_work(&mte->reverse_charge_work);
printk(KERN_INFO"mt5728 111 disable tx\n");
}
static ssize_t enable_tx_show(struct device *dev, struct device_attribute *attr,char *buf)
{
return sprintf(buf, "%d", atomic_read(&mte->is_tx_mode));//atomic_read(&mte->is_tx_mode);// prize add by lpp 20210308
}
static ssize_t enable_tx_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
{
int error;
unsigned int temp;
//struct i2c_client *client = to_i2c_client(dev);
//struct MT5728_dev *chip = i2c_get_clientdata(client);
error = kstrtouint(buf, 10, &temp);
printk("LPP---enable_tx_store temp=%d\n",temp);
#ifdef CONFIG_CHARGER_SC8815A
if(reverse_charger_mode > 0){
printk("LPP---enable_tx_store temp=%d,but reverse_charger_mode:%d,return\n",temp,reverse_charger_mode);
return count;
}
#endif
if (error){
return error;
}
if(!mt5728_init_done){
return count;
}
if(temp==1){
printk(KERN_INFO"mt5728 enable tx start\n");
revere_mode=1;
atomic_set(&mte->is_tx_mode,1);
cancel_delayed_work(&mte->mt5728_tx_disable_work);
schedule_delayed_work(&mte->mt5728_tx_enable_work,msecs_to_jiffies(600));
printk(KERN_INFO"mt5728 enable tx end\n");
}else{
printk(KERN_INFO"mt5728 disable_tx start\n");
revere_mode=0;
atomic_set(&mte->is_tx_mode,0);
cancel_delayed_work(&mte->mt5728_tx_enable_work);
schedule_delayed_work(&mte->mt5728_tx_disable_work,msecs_to_jiffies(600));
printk(KERN_INFO"mt5728 disable_tx end\n");
}
return count;
}
static DEVICE_ATTR(enabletx, 0664, enable_tx_show, enable_tx_store);
void mt5728_switch_tx_to_rx(void)
{
pr_err("[%s]++\n",__func__);
if(!revere_mode){
pr_err("[%s]revere_mode switch off:%d\n",__func__,revere_mode);
return;
}
turn_off_5728(1);
mt_vbus_revere_off();
mtk_set_sc8571_otg(0);
turn_on_otg_charge_mode(0);
mte->tx_count=0;
atomic_set(&mte->is_tx_mode,0);
revere_mode=0;
reverse_timeout_cnt = 0;
cancel_delayed_work(&mte->reverse_charge_work);
msleep(1500);
turn_off_5728(0);
pr_err("[%s]++++\n",__func__);
}
void mt5728_check_cc_change_state(void)
{
if(!revere_mode){
return;
}
mt_vbus_revere_off();
mtk_set_sc8571_otg(0);
turn_on_otg_charge_mode(0);
mte->tx_count=0;
atomic_set(&mte->is_tx_mode,0);
revere_mode=0;
}
EXPORT_SYMBOL(mt5728_check_cc_change_state);
#endif
//prize add by lipengpeng 20210308 end
static int wireless_connect_before_flag = 0;
static bool cc_conect_state = false;
void mt5728_recode_wireless_connect_state(int connect)
{
int state = 0;
state = get_MT5728_status();
cc_conect_state = connect;
pr_err("gezi---%s,mt5728_state:%d,connect:%d\n",__func__,state,connect);
if(!state && connect){
wireless_connect_before_flag = 1;
}
else{
wireless_connect_before_flag = 0;
}
}
EXPORT_SYMBOL(mt5728_recode_wireless_connect_state);
static ssize_t wireless_connect_before_show(struct device *dev, struct device_attribute *attr,char *buf)
{
return sprintf(buf, "%d", wireless_connect_before_flag);
}
static DEVICE_ATTR(wireless_connect_before, 0444, wireless_connect_before_show, NULL);
static ssize_t power_good_gpio_show(struct device *dev, struct device_attribute *attr,char *buf)
{
return sprintf(buf, "%d\n", mte->power_good_gpio);
}
static DEVICE_ATTR(power_good_gpio, 0444, power_good_gpio_show, NULL);
//prize add by lipengpeng 20220623 start
static ssize_t wireless_connect_show(struct device *dev, struct device_attribute *attr,char *buf)
{
if(get_MT5728_status()==0)
{
return sprintf(buf, "%d", 1);
}else{
return sprintf(buf, "%d", 0);
}
}
static DEVICE_ATTR(wireless_connect, 0444, wireless_connect_show, NULL);
static ssize_t wireless_private_protocol_show(struct device *dev, struct device_attribute *attr,char *buf)
{
if(get_MT5728_private_protocol_state())
{
return sprintf(buf, "%d", 1);
}else{
return sprintf(buf, "%d", 0);
}
}
static DEVICE_ATTR(private_protocol_state, 0444, wireless_private_protocol_show, NULL);
//prize add by lipengpeng 20220623 end
static struct attribute* mt5728_sysfs_attrs[] = {
&dev_attr_fast_charging.attr,
&dev_attr_reg.attr,
&dev_attr_adapter_type.attr,
&dev_attr_brushFW.attr,
&dev_attr_TxFirmware.attr,
// &dev_attr_otg.attr,
// &dev_attr_otp.attr,
// &dev_attr_mt5728_en.attr,
// &dev_attr_mt5728_flag.attr,
&dev_attr_epp_set_vout.attr,
NULL,
};
static const struct attribute_group mt5728_sysfs_group = {
.name = "mt5728group",
.attrs = mt5728_sysfs_attrs,
};
static const struct regmap_config MT5728_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
.max_register = 0xFFFF,
};
/**
* [MT5728_send_EPT End Power Transfer Packet]
* @param endreson [end powr Reson]
*/
void MT5728_send_EPT(u8 endreson) {
PktType eptpkt;
eptpkt.header = PP18;
eptpkt.msg_pakt.cmd = ENDPOWERXFERPACKET;
eptpkt.msg_pakt.data[0] = endreson;
MT5728_send_ppp(&eptpkt);
}
void Set_staystate_current(void)
{
pr_info("[%s],call\n", __func__);
wireless_charge_chage_current();
return;
}
EXPORT_SYMBOL(Set_staystate_current);
int get_mt5728_voltage(void){
vuc val;
//if(gpio_get_value(mte->statu_gpio)){
MT5728_read_buffer(mte,REG_VOUT,val.ptr,2);
pr_err("%s: vol read vol=%d\n", __func__,val.value);
//}
return val.value;
}
EXPORT_SYMBOL(get_mt5728_voltage);
int get_mt5728_Iout(void){
vuc val;
//if(gpio_get_value(mte->statu_gpio)){
MT5728_read_buffer(mte,REG_IOUT,val.ptr,2);
pr_err("%s: vol read vol=%d\n", __func__,val.value);
//}
return val.value;
}
static ssize_t mt5728_mtp_crc_slef_check_success(void)
{
int i;
int ret;
vuc val;
// u8 status = 0;
/* wait for 10ms*100=1000ms for status check, typically 300ms */
for (i = 0; i < 100; i++) {
msleep(10);
ret = MT5728_read_buffer(mte, 0x0a, val.ptr, 1);
printk("wait mtp_crc_slef_check:%x,%x\n",val.ptr[0],val.ptr[1]);
if (ret) {
printk("mtp_crc_slef_check: read failed\n");
return ret;
}
if ((val.ptr[0] & MT5728_OP_MODE_EXT_FWCRC_OK) &&
!(val.ptr[0] & MT5728_OP_MODE_EXT_FWCRC_ERR))
return 0;
}
return -1;
}
static ssize_t mt5728_mtp_crc_fw_check_itself(u16 len, u16 crc)
{
int ret;
vuc val;
val.value = crc;
ret = MT5728_write_buffer(mte, REG_FW_CRC_VAL, val.ptr, 2);
val.value = len;
ret += MT5728_write_buffer(mte, REG_FW_CRC_LEN, val.ptr, 2);
val.value = MT5728_RX_FWCRCCHECK;
ret += MT5728_write_buffer(mte, 0x0006, val.ptr, 2);
msleep(100);
ret += mt5728_mtp_crc_slef_check_success();
if (ret) {
printk("crc_check: failed\n");
return ret;
}
printk("[crc_check] succ\n");
return 0;
}
static void mt5728_fwcheck_work_func(struct work_struct* work) {
int mt5728VoutTemp;
u8 fwver[2];
//if(wls_work_online ==1 )
//{
//MT5728_read_buffer(mte, REG_FW_VER, fwver, 2);
//printk(KERN_ALERT "MT5728 fw_version_in_chip : 0x%x%x\n",fwver[0], fwver[1]);
//return;
//}
mt5728VoutTemp = Mt5728_get_vout();
if (mt5728VoutTemp < 0) {
//reserse_charge_online = 1;
//mt5728_ap_open_otg_boost(true);
}
msleep(200); //Wait for Vout voltage to stabilize
mt5728VoutTemp = Mt5728_get_vout();
MT5728_read_buffer(mte, REG_FW_VER, fwver, 2);
printk(KERN_ALERT "MT5728 fw_version_in_chip : 0x%x%x\n",fwver[0], fwver[1]);
if(mt5728_mtp_crc_fw_check_itself(MT5728_MTP_CRC_LEN,MT5728_MTP_CRC_VAL))
{
mt5728_mtp_write_flag = 1;
printk(KERN_ALERT "MT5728 fw_version not match : 0x%x\n",MT5728_FWVERSION);
printk(KERN_ALERT "[%s] brush MTP program\n",__func__);
if(mt5728_mtp_write(0x0000,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin))){
printk(KERN_ALERT "[%s] Write complete, start verification \n",__func__);
if (mt5728_mtp_verify(0x0000,(u8 *)MT5728_mtp_bin,sizeof(MT5728_mtp_bin))) {
printk(KERN_ALERT "[%s] mt5728_mtp_verify OK \n",__func__);
MT5728_read_buffer(mte, REG_FW_VER, fwver, 2);
printk(KERN_ALERT "MT5728 fw_version_in_chip222 : 0x%x%x\n",fwver[1], fwver[0]);
} else {
printk(KERN_ALERT "[%s] mt5728_mtp_verify check program failed \n",__func__);
MT5728_read_buffer(mte, REG_FW_VER, fwver, 2);
printk(KERN_ALERT "MT5728 fw_version_in_chip333 : 0x%x%x\n",fwver[1], fwver[0]);
}
}
//if (mt5728VoutTemp < 0) {
//mt5728_ap_open_otg_boost(false);
// }
mt5728_mtp_write_flag = 0;
}
}
//prize add by lipengpeng 20220611 start
int get_mt5728_charge_protocol(void)
{
return mte->charge_protocol;
}
EXPORT_SYMBOL(get_mt5728_charge_protocol);
//prize add by lipengpeng 20220611 end
void En_Dis_add_current(int i){
vuc protocol;
protocol.ptr[0] = i;
protocol.ptr[1] = 6;//default value in Firmware IIC address REG_CURFUNC+1
printk(" En_Dis_add_current i=%d protocol.ptr[0]=%02x\n",i,protocol.ptr[0]);
//MT5728_write_buffer(mte, REG_CURFUNC, protocol.ptr,1);
}
EXPORT_SYMBOL(En_Dis_add_current);
#if 1
static void MT5728_add_current(void){
vuc protocol;
vuc epp;
long voltage = 9000;
long tcurrent =0;
long tvoltage =0;
long maxpower =0;
long powertemp =0;
long maxchargecurrent = 1000000;
epp.value =0;
protocol.value =0;
//mte->charge_current = 1000000;
tvoltage = get_mt5728_voltage();
pr_err("[%s] Rx Vout:%d\n", __func__,tvoltage);
tcurrent = get_mt5728_Iout();
pr_err("[%s] Rx Iout:%d\n", __func__,tcurrent);
if(1){
MT5728_read_buffer(mte, 0x00a7, protocol.ptr,1); // tx type
pr_err("[%s]: protocol read 1 : %02x%02x protocol.value =0x%04x protocol.value =%d\n",__func__,protocol.ptr[0],protocol.ptr[1],protocol.value,protocol.value);
if(protocol.ptr[0]== 1){
mte->charge_protocol = BPP;
mte->wireless_max_power = 5;
voltage = 5000;
maxchargecurrent = 1000000;
pr_info("[%s]: BPP Load power is recommended to be less than %dW\n", __func__,mte->wireless_max_power);
} else if(protocol.ptr[0] == 2){
mte->charge_protocol = AFC;
mte->wireless_max_power = 10;
voltage = 9000;
maxchargecurrent = 1100000;
pr_info("[%s]: AFC Load power is recommended to be less than %dW\n", __func__,mte->wireless_max_power);
} else if(protocol.ptr[0] == 3){
mte->charge_protocol = EPP;
MT5728_read_buffer(mte,REG_MAX_POWER,epp.ptr,1);
epp.ptr[0] = epp.ptr[0]/2;
voltage = 9000;
pr_info("[%s]: EPP Load power is recommended to be less than %dW\n", __func__,epp.ptr[0]);
mte->wireless_max_power = epp.ptr[0];
//if(mte->wireless_max_power > 15) mte->wireless_max_power = 15;
if (mte->wireless_max_power > mte->rx_power_cap){
dev_info(mte->dev,"%s: limit rx power to %d from %d\n",mte->rx_power_cap,mte->wireless_max_power);
mte->wireless_max_power = mte->rx_power_cap;
}
maxchargecurrent = mte->wireless_max_power * 1000 / 9 * 92 *10;
} else {
chr_err("[%s]: read 0x00a7 info no BPP EPP AFC protocol\n", __func__);
}
}
// if(mte->wireless_max_power == 5) maxpower = mte->wireless_max_power * 1000;
//else maxpower = mte->wireless_max_power * 1000;
maxpower = mte->wireless_max_power * 1000 * mte->rx_efficiency / 100;
pr_err("[%s]: wireless system support power = %d W\n",__func__,mte->wireless_max_power);
pr_err("[%s]: Max charge maxchargecurrent = %d mA\n",__func__,(maxchargecurrent/1000));
pr_err("[%s]: Get wireless output voltage = %d mV\n",__func__,voltage);
tcurrent = mte->input_current / 1000;
pr_err("[%s]: last time,Set input tcurrent = %d mA\n",__func__,tcurrent);
if(tcurrent == 0) tcurrent = 100;
powertemp = voltage * tcurrent / 1000 ;
pr_err("[%s]: powertemp = %d , maxpower = %d\n",__func__,powertemp,maxpower);
if(powertemp < maxpower ){
powertemp = powertemp + 2000;
if(powertemp > maxpower) {
powertemp = maxpower;
pr_info("[%s] DISABLE_ADD_CURRENT INT!\n", __func__);
En_Dis_add_current(DISABLE_ADD_CURRENT);
}
pr_info("[%s] add power = %d mW\n", __func__,powertemp);
mte->input_current = powertemp * 1000 / voltage * 1000;
if(mte->charge_protocol == BPP){
if(mte->input_current > 1000000) mte->input_current = 1000000;
}
if(mte->charge_protocol == AFC){
if(mte->input_current > 1100000) mte->input_current = 1100000;
}
if(mte->input_current > maxchargecurrent) mte->input_current= maxchargecurrent;
mte->charge_current = powertemp / 4 * 1000;
//#if defined(CONFIG_PRIZE_ONLY5W_DISPLAY_15W)
if(mte->charge_protocol == BPP)
{
mte->input_current = 1000000;
mte->charge_current = 1000000;
}
/*
if(mte->charge_protocol == EPP && mte->input_current > 1000000){
if(mte->wireless_max_power > 10){
mte->input_current = 1300000;
mte->charge_current = 2650000;
}
else if(mte->wireless_max_power == 5){
mte->input_current = 1000000;
mte->charge_current = 1000000;
}
else{
mte->input_current = 1100000;
mte->charge_current = 1800000;
}
}
*/
if(mte->charge_protocol == EPP)
{
mte->input_current = 1200000;
mte->charge_current = 1200000;
}
//#endif
//prize add by lipengpeng 20210305 end
pr_info("[%s] Set input_current = %d, Set charge_current = %d\n", __func__,mte->input_current,mte->charge_current);
Set_staystate_current();
schedule_delayed_work(&mte->add_current_work,msecs_to_jiffies(100));
}else{
pr_info("[%s] return!\n", __func__);
En_Dis_add_current(DISABLE_ADD_CURRENT);
return;
}
}
#endif
//mike add 2023.1.4
static void mt5728_removed_form_tx(void) {
mte->mt5728_ldo_on_flag = 0;
printk(KERN_ALERT "mt5728_removed_form_tx\n");
}
/**
* [mt5728_set_pmic_input_current_ichg description]
* @param input_current [mA]
*/
static void mt5728_set_pmic_input_current_ichg(int input_current,int charge_current) {
// charger_dev_set_input_current(primary_charger,input_current * 1000);
mte->input_current = input_current * 1000;
mte->charge_current = charge_current * 1000;
pr_info("[%s] Set input_current = %d, Set charge_current = %d\n", __func__,mte->input_current,mte->charge_current);
Set_staystate_current();
}
static void mt5728_charger_work_func(struct work_struct* work) {
int vbus_now = 0;
int vbus_read_temp = 0;
vuc val;
printk(KERN_ALERT "%s\n",__func__);
Mt5728_get_vrect();
vbus_read_temp = Mt5728_get_vout();
if ((vbus_read_temp >= 0) && (vbus_read_temp <= 20000)) {
vbus_now = Mt5728_get_vout();
}
//check if rx put on tx surface,if 1 rx removed from tx
if(((vbus_now < 1000) && (mte->mt5728_ldo_on_flag == 1))|| (vbus_read_temp == -1)) {
printk(KERN_ALERT "%s %d 111\n",__func__,powergood_err_cnt);
powergood_err_cnt++;
if(powergood_err_cnt > 20) { //Cancel wireless charging icon display
mt5728_removed_form_tx();
return;
} else {
printk(KERN_ALERT "%s 222\n",__func__);
schedule_delayed_work(&mte->charger_work, msecs_to_jiffies(100));
return;
}
} else {
powergood_err_cnt = 0;
}
printk(KERN_ALERT "%s 333 %d\n",__func__,powergood_err_cnt);
if(Private_state == 0) { // bpp,epp
//After waiting for 10 seconds, change the PMIC input current
if(setup_iout_start_cnt < 100) {
printk(KERN_ALERT "%s 444 %d\n",__func__,setup_iout_start_cnt);
setup_iout_start_cnt++;
if (setup_iout_start_cnt == 70) {
if (mt5728_epp_ctrl_vout_flag) {
val.value = rx_vout_max;
printk(KERN_ALERT "mt5728 epp set Vout to:%d,ptpower%d\n",rx_vout_max,mte->wireless_max_power);
MT5728_write_buffer(mte, REG_VOUTSET, val.ptr, 2);
val.value = VOUT_CHANGE;
MT5728_write_buffer(mte, REG_CMD, val.ptr, 2);
mt5728_epp_ctrl_vout_flag = 0;
msleep(100);
set_rx_ocp(2600);
}
}
} else {
printk(KERN_ALERT "%s 555 %d\n",__func__,current_change_interval_cnt);
//Change one step every 500ms
if(current_change_interval_cnt++ > 5) {
current_change_interval_cnt = 0;
// EPP check vout > 8V,2023.2.20
if((rx_vout_max == 9000) && (vbus_now > 8000)) {
if((input_current_limit < rx_iout_max)) {
input_current_limit += 100;
}
mt5728_set_pmic_input_current_ichg(input_current_limit,3000);
} else {
printk(KERN_ALERT "%s mt5728 vout < 8000: %d\n",__func__,vbus_now);
}
// BPP check vout > 4V,2023.2.20
if((rx_vout_max == 5000) && (vbus_now > 4000)) {
if((input_current_limit < rx_iout_max)) {
input_current_limit += 100;
}
mt5728_set_pmic_input_current_ichg(input_current_limit,3000);
} else {
printk(KERN_ALERT "%s mt5728 vout < 4000: %d\n",__func__,vbus_now);
}
}
}
}
if(Private_state == 2) { //maxic tx , Private charging protocol
//Turn on the charge pump
}
}
static bool mt5728_get_tx_cep_cnt_close_tx(void)
{
vuc cepcnt;
MT5728_read_buffer(mte, 0x00c0, cepcnt.ptr, 2);
if(cepcnt.value != mt5728_tx_cep_cnt_old) {
mt5728_tx_cep_cnt_timeout = 0;
mt5728_tx_cep_cnt_old = cepcnt.value;
} else {
mt5728_tx_cep_cnt_timeout++;
}
if(mt5728_tx_cep_cnt_timeout > 600) {
pr_err("gezi---%s---time out\n",__func__);
return true;
}
return false;
}
static bool mt5728_check_tx_slection_have_ac_flag(void)
{
/*tx_slection_have_ac_flag--|<7C><>?????<3F><>0x068A----?<3F><>??????<3F><><EFBFBD><EFBFBD>???<3F><>2*/
vuc val;
vuc txinit;
MT5728_read_buffer(mte,REG_STABILITY,txinit.ptr,2);
if(txinit.value == 0x5555){
pr_err("gezi---%s---txinit.value == 0x5555\n",__func__);
return true;
}
if(MT5728_read_buffer(mte,0x068A,val.ptr,1) < 0){
pr_err("gezi---%s---read err\n",__func__);
return false;
}
if(val.ptr[0]){
pr_err("gezi---%s---0x068A flag true\n",__func__);
return true;
}
return false;
}
static void mt5728_reverse_work_func(struct work_struct* work) {
bool force_switch_to_rx0 = false;
bool force_switch_to_rx1 = false;
force_switch_to_rx0 = mt5728_check_tx_slection_have_ac_flag();
force_switch_to_rx1 = mt5728_get_tx_cep_cnt_close_tx();
pr_err("gezi[%s]^_^ -start..%d %d %d %d %d\n", \
__func__,mte->rxdetect_flag,mte->rxremove_flag,reverse_timeout_cnt,force_switch_to_rx0,force_switch_to_rx1);
if(force_switch_to_rx0 || force_switch_to_rx1){
goto force_switch;
}
if(mte->rxdetect_flag == 1) {
//if(mte->rxremove_flag == 1) {
// mte->rxdetect_flag = 0;
//mte->rxremove_flag = 0;
reverse_timeout_cnt = 0;
schedule_delayed_work(&mte->reverse_charge_work, msecs_to_jiffies(200));
return;
// } else {
//Check the remaining battery capacity
//Check battery temperature
//reverse_timeout_cnt = 0;
//}
} else {
reverse_timeout_cnt++;
if(reverse_timeout_cnt > 600) { //RX put on timeout, active shutdown
//mt5728_reverse_charge(0);
//is_reverse_charge_work_running = false;
force_switch:
is_ping = false;
mt5728_switch_tx_to_rx();
pr_err("gezi-------%s------exit\n",__func__);
return;
}
}
schedule_delayed_work(&mte->reverse_charge_work, msecs_to_jiffies(200));
}
void print_curfunc_info(void){
vuc protocol;
protocol.value =0;
if(1){
//MT5728_read_buffer(mte, REG_CURFUNC, protocol.ptr,1);
pr_err("%s: protocol read 1 : %02x%02x protocol.value =0x%04x protocol.value =%d\n",__func__,protocol.ptr[0],protocol.ptr[1],protocol.value,protocol.value);
}else{
pr_err("%s: statu_gpio is low\n",__func__);
}
}
ssize_t Mt5728_set_vout(struct device* cd, struct device_attribute *attr, const char* buf, size_t len)
{
vuc val;
int error;
unsigned int a;
error = kstrtouint(buf, 10, &a);
val.value = (unsigned short)a;
printk(KERN_ALERT "%s,write reg_cmd : 0x%04x,\n", __func__, val.value);
MT5728_write_buffer(mte, REG_VOUTSET, val.ptr, 2);
val.value = VOUT_CHANGE;
MT5728_write_buffer(mte, REG_CMD, val.ptr, 2);
printk(KERN_ALERT "%s,write reg_cmd : 0x%04x,\n", __func__, val.value);
return 0;
}
int set_rx_ocp(uint16_t ocp)
{
vuc temp;
temp.value = ocp;
MT5728_write_buffer(mte, 0x0034, temp.ptr, 2); // reg ocp
temp.value = OCP_CHANGE;
MT5728_write_buffer(mte, REG_CMD, temp.ptr, 2);
return 0;
}
static ssize_t Mt5728_get_TxPeriod(void) {
vuc period;
if(MT5728_read_buffer(mte,0x0020,period.ptr,2) < 0) {
printk(KERN_ALERT "%s,Mt5728_get_period error!\n", __func__);
} else {
// printk(KERN_ALERT "%s,Mt5728_get_period : %d,%d KHz !\n", __func__, period.value,(80000/(period.value + 1)));
}
return period.value;
}
ssize_t Mt5728_get_iout(void)
{
vuc iout;
if(MT5728_read_buffer(mte,REG_IOUT,iout.ptr,2) < 0) {
printk(KERN_ALERT "%s,Mt5728_get_iout error!\n", __func__);
} else {
// printk(KERN_ALERT "%s,Mt5728_get_iout : %dmA !\n", __func__, iout.value);
}
return iout.value;
}
ssize_t Mt5728_get_vout(void)
{
vuc vout;
if(MT5728_read_buffer(mte,REG_VOUT,vout.ptr,2) < 0) {
printk(KERN_ALERT "%s,Mt5728_get_vout error!\n", __func__);
return -1;
}
Mt5728_get_iout();
Mt5728_get_TxPeriod();
//printk(KERN_ALERT "%s,Mt5728_get_vout_old : %d !\n", __func__,mt5728_vout_old);
//if (abs(vout.value - mt5728_vout_old) > 1000) {
mt5728_vout_old = vout.value;
// printk(KERN_ALERT "%s,Mt5728_get_vout : %dmV !\n", __func__, vout.value);
//}
return vout.value;
}
#if 1
static ssize_t Mt5728_get_vrect(void) {
vuc vout;
if(MT5728_read_buffer(mte,REG_VRECT,vout.ptr,2) < 0) {
return -1;
}
//printk(KERN_ALERT "%s,Mt5728_get_vrect_old : %d !\n", __func__,mt5728_vout_old);
//if (abs(vout.value - mt5728_vrect_old) > 1000) {
mt5728_vrect_old = vout.value;
printk(KERN_ALERT "%s,Mt5728_get_vrect : %dmV !\n", __func__, vout.value);
//}
return vout.value;
}
#endif
//prize add by lipengpeng 20210419 start
/*
* vout,rx vout,mv
* return 0,OK,others failed
*/
bool mt5728_get_charge_done(void)
{
if(!mt5728_init_done){
pr_err("%s not init done!!!\n",__func__);
return false;
}
return mte->chg_done;
}
EXPORT_SYMBOL(mt5728_get_charge_done);
void mt5728_set_charge_done(bool done)
{
if(!mt5728_init_done){
pr_err("%s not init done!!!\n",__func__);
return;
}
mte->chg_done = done;
}
EXPORT_SYMBOL(mt5728_set_charge_done);
int set_rx_vout(uint16_t vout)
{
vuc temp;
uint16_t pre_vout=0;
MT5728_read_buffer(mte, REG_VOUTSET, temp.ptr, 2);
pre_vout= temp.value;
//mike debug 20231010
// if (pre_vout == vout) {
// return -1; /*vout already set or vout set running*/
// }
temp.value = vout;
MT5728_write_buffer(mte, REG_VOUTSET, temp.ptr, 2);
temp.value = VOUT_CHANGE;
MT5728_write_buffer(mte, REG_CMD, temp.ptr, 2);
msleep(10);
return 0;
}
void mt5728_SetFodPara(void) {
MT5728_write_buffer(mte, REG_FOD, (unsigned char *)mt5728fod, 16);
//MT5728_write_buffer(mte, REG_FODREG_FOD_EPP, (unsigned char *)mt5728fod_epp, 16);
}
//add 20230717
void mt5728_SC_FirmWare_AutoVout_TargertIout_Start(void) {
vuc temp;
temp.value = 1;
MT5728_write_buffer(mte, 0x00f0, temp.ptr, 1);
}
void mt5728_SC_FirmWare_AutoVout_TargertIout_Stop(void) {
vuc temp;
temp.value = 0;
MT5728_write_buffer(mte, 0x00f0, temp.ptr, 1);
}
void mt5728_SC_FirmWare_AutoVout_TargertIout_Set(u16 targetIout) {
vuc temp;
temp.value = targetIout;
MT5728_write_buffer(mte, 0x00ee, temp.ptr, 2);
}
void mt5728_send_ask_maxicDemoKey(void) {
PktType eptpkt;
eptpkt.header = PP38;
eptpkt.msg_pakt.cmd = 0x58;
eptpkt.msg_pakt.data[0] = 0x10;
eptpkt.msg_pakt.data[1] = 0x15;
MT5728_send_ppp(&eptpkt);
}
void mt5728_send_ask_EPPEXTENDSYNC(void) {
PktType eptpkt;
eptpkt.header = PP28;
eptpkt.msg_pakt.cmd = 0x90;
eptpkt.msg_pakt.data[0] = 0x32;
MT5728_send_ppp(&eptpkt);
}
/*
#define REG_PLDO_TH_MW 0x0038
static void mt5728_set_Pldo_th(unsigned short pldoTh)
{
vuc val;
val.value = pldoTh;
pr_err("[%s]---0x%x\n",__func__,pldoTh);
MT5728_write_buffer(mte, REG_PLDO_TH_MW, val.ptr, 2);
}
static void mt5728_set_Pldo(int enable)
{
if(enable){
mt5728_set_Pldo_th(0x0bb8);
}
else{
mt5728_set_Pldo_th(0xffff);
}
}
*/
int battery_get_uisoc(void)
{
union power_supply_propval prop;
if(IS_ERR_OR_NULL(mte->bms_psy)){
mte->bms_psy = power_supply_get_by_name("battery");
if(IS_ERR_OR_NULL(mte->bms_psy)){
pr_err("gezi get bms_psy error\n");
//*tbat = 50;
return 50;
}
goto to;
}
to:
power_supply_get_property(mte->bms_psy,POWER_SUPPLY_PROP_CAPACITY, &prop);
return prop.intval;
}
EXPORT_SYMBOL(battery_get_uisoc);
#ifndef TX_5815_DEMO_NO_SHA1
//20211013, ask key, 68 59 80 01 76 6d 2e
void mt5728_send_ask_maxickey(void) {
PktType eptpkt;
u8 rand = 0;
get_random_bytes(&rand, sizeof(rand));
eptpkt.header = PP68;
eptpkt.msg_pakt.cmd = 0x59;
eptpkt.msg_pakt.data[0] = (unsigned char)rand%64;
eptpkt.msg_pakt.data[1] = 0x01;
sha1_verify((unsigned char *)&eptpkt.msg_pakt.data, SHA_GENERATE_MODE);
// eptpkt.data[0] = 0x80;
// eptpkt.data[1] = 0x01;
// eptpkt.data[2] = 0x76;
// eptpkt.data[3] = 0x6d;
// eptpkt.data[4] = 0x2e;
MT5728_send_ppp(&eptpkt);
printk("hct_drv_ mt5728_send_ask_maxickey Tx.rand = 0x%x. \n", rand);
}
void mt5728_send_ask_ACK(void) {
PktType eptpkt;
eptpkt.header = PP18;
eptpkt.msg_pakt.cmd = 0xff;
eptpkt.msg_pakt.data[0] = 0xff;
MT5728_send_ppp(&eptpkt);
}
#endif
#ifdef TX_5815_DEMO_NO_SHA1
static void mt5728_Private_packet_proc_work_func(struct work_struct* work){
// unsigned char fsk_data_tmp[10];
vuc val;
pr_err("gezi %s-------Private_state:%d,private_fskrecv_flag:%d",__func__,Private_state,private_fskrecv_flag);
switch(Private_state){
case 0: //sha1 key handle
//USE_5815_DEMO_PCB //2022.8.15
if (Private_packet_retrycnt++ < 3)
{
mt5728_send_ask_maxicDemoKey();
msleep(500);
if (private_fskrecv_flag == 1)
{
private_fskrecv_flag = 0;
MT5728_read_buffer(mte, REG_BC, val.ptr, 2);
if (val.ptr[0] == 0x1e) //debug sha1
{
printk(KERN_ALERT "MT5728 Demo Tx verify pass 20220815\n");
rx_iout_max = 100;//1500;
Private_state = 1;
Private_packet_retrycnt = 0;
}
}
schedule_delayed_work(&mte->mt5728_Private_packet_proc_work ,msecs_to_jiffies(500));
}else {
//return -1; //sha1 key handle fail
return;
}
break;
case 1:
if (Private_packet_retrycnt++ < 3)
{
mt5728_send_ask_EPPEXTENDSYNC();
msleep(500);
if (private_fskrecv_flag == 1)
{
private_fskrecv_flag = 0;
MT5728_read_buffer(mte, REG_BC, val.ptr, 2);
if (val.ptr[0] == 0x1e) //ack
{
val.value = 0x28;
MT5728_write_buffer(mte, REG_MAX_POWER, val.ptr, 1);
//MT581X TX, MAXIC TX Key ACK,30W
rx_vout_max = 19000;
rx_iout_max = 2050;
Private_state = 2;
mte->charge_protocol = MAXIC_PRIVATE;
//return 0;
pr_err("gezi %s-------Private protocol get success!!!\n",__func__);
mte->private_protocol_state = 1;
if (battery_get_uisoc() >= 90) {
mte->force_swchg = 1;
pr_err("[%s]uisoc > 90(%d),switch to swchg\n",__func__,battery_get_uisoc());
}
else {
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
if(mt5728_40w_init_done > 0){
mt5728_wireless_algo_start();
}
else{
pr_err("[%s]40w algo init fail,don't start algo!\n",__func__);
}
#endif
}
return;
}
}
schedule_delayed_work(&mte->mt5728_Private_packet_proc_work ,msecs_to_jiffies(500));
}else {
//return -1; //sha1 key handle fail
return;
}
break;
default:
break;
}
}
#else
static void mt5728_Private_packet_proc_work_func(struct work_struct* work){
vuc val;
int res;
unsigned char fsk_data_tmp[3] = {0};
printk("hct_drv_%s(),LINE=%d,Private_state=%d. Private_packet_retrycnt = %d. private_fskrecv_flag = %d. \n",
__func__,__LINE__, Private_state, Private_packet_retrycnt, private_fskrecv_flag);
switch(Private_state){
case 0: //sha1 key handle
if (Private_packet_retrycnt++ < 5)
{
mt5728_send_ask_maxickey();
msleep(500);
//mt5728_set_Pldo(1);
if (private_fskrecv_flag == 1)
{
private_fskrecv_flag = 0;
MT5728_read_buffer(mte, REG_BC, val.ptr, 2);
printk("hct_drv_ mt5728 Tx. val.value = 0x%x. \n", val.value);
if (val.ptr[0] == 0x6f) //debug sha1
{
//MT581X TX, MAXIC TX Key ACK,30W
// rx_vout_max = 16000;
// rx_iout_max = 1500;
MT5728_read_buffer(mte, REG_BC+2, fsk_data_tmp, 3);
res = sha1_verify((unsigned char *)&fsk_data_tmp, SHA_VERIFY_MODE);
printk("hct_drv_ mt5728 sha1 res:%d\n",res);
if (res) {
Private_state = 1;
Private_packet_retrycnt = 0;
printk("hct_drv_ mt5728 Tx verify pass\n");
// g680_wireless_15w_flag =0;
mt5728_send_ask_ACK();
msleep(400);
mt5728_send_ask_ACK();
msleep(400);
mt5728_send_ask_ACK();
msleep(400);
}
}
}
schedule_delayed_work(&mte->mt5728_Private_packet_proc_work ,msecs_to_jiffies(500));
}
else
{
// g680_wireless_15w_flag =1;
// schedule_delayed_work(&chip->charger_work_15w_api, msecs_to_jiffies(100));
mt5728_connect_set_over_time();
printk("hct_drv_%s(),LINE=%d,g680_wireless_15w_flag==1\n",__func__,__LINE__);
return;
}
break;
case 1:
if (Private_packet_retrycnt++ < 5)
{
mt5728_send_ask_EPPEXTENDSYNC();
msleep(500);
if(private_fskrecv_flag == 1)
{
private_fskrecv_flag = 0;
MT5728_read_buffer(mte, REG_BC, val.ptr, 2);
if (val.ptr[0] == 0x1e) //ack
{
val.value = 0x28;
MT5728_write_buffer(mte, REG_MAX_POWER, val.ptr, 1);
//MT581X TX, MAXIC TX Key ACK,30W
// rx_vout_max = 16000;
//rx_iout_max = 100;//1500;
rx_iout_max = 2100;
Private_state = 2;
//g680_wireless_15w_flag =0;
//printk("hct_drv_%s(),LINE=%d,g680_wireless_15w_flag==0\n",__func__,__LINE__);
mte->charge_protocol = MAXIC_PRIVATE;
pr_err("gezi %s-------Private protocol get success!!!\n",__func__);
mte->private_protocol_state = 1;
if (battery_get_uisoc() >= 90) {
mte->force_swchg = 1;
pr_err("[%s]uisoc > 90(%d),switch to swchg\n",__func__,battery_get_uisoc());
}
else {
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
if(mt5728_40w_init_done > 0){
mt5728_wireless_algo_start();
}
else{
pr_err("[%s]40w algo init fail,don't start algo!\n",__func__);
}
#endif
}
return;
}
else{
pr_err("%s-------REG_BC = 0x%x,0x%x\n",__func__,val.ptr[0],val.ptr[1]);
}
}
schedule_delayed_work(&mte->mt5728_Private_packet_proc_work ,msecs_to_jiffies(500));
}
else {
// g680_wireless_15w_flag =1;
// schedule_delayed_work(&chip->charger_work_15w_api, msecs_to_jiffies(100));
mt5728_connect_set_over_time();
printk("hct_drv_%s(),LINE=%d,g680_wireless_15w_flag==1\n",__func__,__LINE__);
return;
}
break;
default:
break;
}
}
#endif
ssize_t Mt5728_get_vsetflag_cep(void)
{
vuc VsetFlag;
vuc cep;
VsetFlag.value = 0;
cep.value = 0;
if(MT5728_read_buffer(mte,0x040d,VsetFlag.ptr,1) < 0) { //VsetFlag
printk("%s read VsetFlag error!\n", __func__);
return -1;
}
if(MT5728_read_buffer(mte,0x0073,cep.ptr,1) < 0) { //cep
printk("%s read cep error!\n", __func__);
return -1;
}
printk(KERN_ALERT "%s,Mt5728_get_VsetFlag:%d ,cep:%d !\n", __func__, VsetFlag.value,cep.value);
return 0;
}
void mt5728_private_packet_hand_work(int delay_time)
{
pr_err("++[%s]delay_time:%d\n",__func__,delay_time);
schedule_delayed_work(&mte->mt5728_Private_packet_proc_work,msecs_to_jiffies(delay_time));
}
void mt5728_send_pp18_packet(int delay_time)
{
pr_err("++[%s]delay_time:%d\n",__func__,delay_time);
schedule_delayed_work(&mte->mt5728_pp18_packet_send_work,msecs_to_jiffies(delay_time));
}
void mt5728_connect_over_time_work_schedule(int delay_time)
{
pr_err("++[%s]delay_time:%d\n",__func__,delay_time);
schedule_delayed_work(&mte->mt5728_connect_over_time_work,msecs_to_jiffies(delay_time));
}
void MT5728_irq_handle(void) {
vuc val;
vuc temp,scmd,fclr;
int iic_rf,delay_time = 10000;
scmd.value = 0;
pr_info("----------------MT5728_delayed_work-----------------------\n");
pr_info("MT5728_delayed_work------vrect:%d,vout:%d,iout:%d\n",Mt5728_get_vrect(),Mt5728_get_vout(),Mt5728_get_iout());
//pr_err("[%s] vbus = %d\n",__func__,battery_get_vbus());
temp.value = MT5728ID;
iic_rf = MT5728_write_buffer(mte,REG_CHIPID,temp.ptr,2);
if(iic_rf < 0){
pr_err("[%s] Chip may not be working\n",__func__);
return;
}
MT5728_read_buffer(mte,REG_FW_VER,temp.ptr,2);
printk("%s: fw_ver 0x%2x%2x\n",__func__,temp.ptr[0],temp.ptr[1]);
MT5728_read_buffer(mte,0x04,temp.ptr,2);
printk("%s: System mode %x\n",__func__,temp.ptr[1]);
if(temp.ptr[1] & RXMODE){
pr_info("[%s] The chip works in Rx mode\n",__func__);
MT5728_read_buffer(mte, REG_INTFLAG, val.ptr, 2);
fclr.value = val.value;
pr_info("[%s] REG_INTFLAG value:0x%04x\n", __func__, val.value);
if(val.value == 0){
pr_info("[%s] There's no interruption here\n", __func__);
return;
}
print_curfunc_info();
if (val.value & INT_POWER_ON) {
pr_info("[%s] Interrupt signal: PowerON 01\n", __func__);
mte->wireless_max_power = 0;
mte->charge_protocol = PROTOCOL_UNKNOWN;
mte->input_current = 500000;
mte->charge_current = 500000;
rx_vout_max = 5000;
rx_iout_max = 1000;
setup_iout_start_cnt = 0;
input_current_limit = 100;
pr_info("[%s] Interrupt signal: PowerON 02\n", __func__);
//mike 2023.1.4
mt5728_set_pmic_input_current_ichg(100,100);
Private_packet_retrycnt = 0;
Private_state = 0;
//mt5728_set_Pldo(0);
// schedule_delayed_work(&mte->charger_work, msecs_to_jiffies(100));
}
if (val.value & INT_LDO_ON) {
pr_info("[%s] Interrupt signal:LDO ON\n", __func__);
//mt5728_ldo_on_flag = 1;
}
if (val.value & INT_RX_READY) {
pr_info("[%s] Interrupt signal:MT5728 is Ready\n", __func__);
}
if (val.value & INT_LDO_OFF) {
pr_info("[%s] Interrupt signal:MT5728 LDO_OFF\n", __func__);
if(val.value == 0x80){
pr_info("[%s] There's no interruption here\n", __func__);
return;
}
}
if (val.value & INT_FSK_RECV) {
pr_info("[%s] Interrupt signal:FSK received successfully\n", __func__);
mte->fsk_status = FSK_SUCCESS;
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
Mt5728_get_fsk_buf_0_1();
#endif
private_fskrecv_flag = 1;
//read REG_BC
}
if (val.value & INT_FSK_SUCCESS) {
pr_info("[%s] Interrupt signal:FSK received successfully\n", __func__);
mte->fsk_status = FSK_SUCCESS;
//read REG_BC
}
if (val.value & INT_FSK_TIMEOUT) {
pr_info("[%s] Interrupt signal:Failed to receive FSK\n", __func__);
mte->fsk_status = FSK_FAILED;
//read REG_BC
}
if(val.value & INT_BPP){
pr_info("[%s] Interrupt signal:Tx BPP\n", __func__);
pr_info("[%s] Load power is recommended to be less than 5W\n", __func__);
mte->wireless_max_power = 5;
mte->charge_protocol = BPP;
mte->input_current = 1000000;
mte->charge_current = 1000000;
Set_staystate_current();
//mt5728_set_Pldo(1);
schedule_delayed_work(&mte->add_current_work,msecs_to_jiffies(400));
//schedule_delayed_work(&mte->mt5728_connect_over_time_work,msecs_to_jiffies(10000));
mt5728_connect_over_time_work_schedule(10000);
}
if(val.value & INT_EPP){
vuc epp;
pr_info("[%s] Interrupt signal:Tx EPP\n", __func__);
private_fskrecv_flag = 0;
MT5728_read_buffer(mte,REG_MAX_POWER,epp.ptr,1);
epp.ptr[0] = epp.ptr[0]/2;
pr_info("[%s] Load power is recommended to be less than %dW\n", __func__,epp.ptr[0]);
mte->wireless_max_power = epp.ptr[0];
if (mte->wireless_max_power > mte->rx_power_cap){
dev_info(mte->dev,"%s: limit rx power to %d from %d\n", __func__, mte->rx_power_cap,mte->wireless_max_power);
mte->wireless_max_power = mte->rx_power_cap;
}
mte->charge_protocol = EPP;
mte->input_current = 1000000;
mte->charge_current = 1000000;
mt5728_epp_ctrl_vout_flag = 1;
if (mte->wireless_max_power < 15) {
rx_vout_max = 9000;
rx_iout_max = 1500;
} else {
rx_vout_max = 9000;
rx_iout_max = 1500;
}
//Set_staystate_current();
/*set vout to 9000mv*/
//set_rx_vout(9000);
//prize add by lipenpeng 20210419 end
pr_info("[%s] mt5728 Private_packet_check_work start!!!\n",__func__);
if (gezi_boot_mode == 8 || gezi_boot_mode == 9){
delay_time = 10000;
}
else{
if(mte->boot_complete){
delay_time = 10000;
}
else{
delay_time = 30000;
}
}
if(battery_get_uisoc() >= 90){
pr_err("gezi:uisoc >= 90,need't private_packet_hand\n");
mt5728_send_pp18_packet(delay_time + 1000);
}
else{
mt5728_private_packet_hand_work(delay_time);
}
//schedule_delayed_work(&mte->mt5728_connect_over_time_work,msecs_to_jiffies(10000));
//mt5728_connect_over_time_work_schedule(10000);
}
if (val.value & INT_AFC_SUPPORT) {
pr_info("[%s] Interrupt signal:Tx support samsung_afc\n", __func__);
pr_info("[%s] Load power recommended to 9W\n", __func__);
mte->wireless_max_power = 10;
mte->charge_protocol = AFC;
mte->input_current = 500000;
mte->charge_current = 500000;
//Set_staystate_current();
//prize add by lipengpeng 20210419 start Samsung agreement 9V
fast_vfc(9000);
//prize add by lipengpeng 20210419 end
}
if(val.value & INT_ADDCURRENT){
pr_info("[%s] Add current\n", __func__);
//mike debug 20231010
if(0){
MT5728_add_current();
}
}
if(val.value & INT_AC_MISSING){
pr_info("[%s] AC MISSING\n", __func__);
}
pr_info("[%s] Get power wireless charging chip %dW\n", __func__,mte->wireless_max_power);
}
if(temp.ptr[1] & TXMODE){
pr_info("[%s] The chip works in Tx mode\n",__func__);
MT5728_read_buffer(mte, REG_INTFLAG, val.ptr, 2);
fclr.value = val.value;
pr_info("[%s] REG_INTFLAG value:0x%04x\n", __func__, val.value);
//prize add by lipengpeng 20210408 if usb charger close otg start
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
if((val.value & INT_CHIP_DISABLE)&&(revere_mode==1)){
printk(KERN_INFO"lpp----disable otg charge111\n");
//mt_vbus_revere_off();
printk(KERN_INFO"lpp----disable otg charge222\n");
//turn_on_otg_charge_mode(0);//GPIO109--->low
//turn_off_rever_5725(0);//OD5-->low
//set_otg_gpio(0);//OD7--->low
mte->tx_count=0;
//mt_vbus_reverse_off_limited_current();// prize add by lipengpeng 20210322 close otg voltage
atomic_set(&mte->is_tx_mode,0);
revere_mode=0;
}
#endif
//prize add by lipengpeng 20210408 if usb charger close otg end
if(val.value == 0){
pr_info("[%s] There's no interruption here\n", __func__);
return;
}
if(val.value & INT_DETECT_RX){
pr_info("[%s] Found RX close\n", __func__);
}
if(val.value & INT_OCPFRX){
if(mt5728_ocp_reopen_tx_cnt > 0) {
mt5728_tx_modestability_start();
mt5728_ocp_reopen_tx_cnt--;
}
else {
//prize add by lipengpeng 20210507 start
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
atomic_set(&mte->is_tx_mode,3); //Reverse charging device abnormal, stop reverse charging
#endif
}
//prize add by lipengpeng 20210507 end
pr_info("[%s] TX OCP protection\n", __func__);
}
if(val.value & INT_TX_AC_VALID){
pr_info("[%s]INT_TX_AC_VALID triggr\n", __func__);
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
mt5728_switch_tx_to_rx();
#endif
}
// if(val.value & INT_FODDE){
// vuc fod;
// pr_info("[%s] TX FOD\n", __func__);
// MT5728_read_buffer(mte,REG_F_TXPOWER,fod.ptr,2);
// pr_info("[%s] TX_power:%d mW\n", __func__,fod.value);
// MT5728_read_buffer(mte,REG_F_RXPOWER,fod.ptr,2);
// pr_info("[%s] RX_power:%d mW\n", __func__,fod.value);
// MT5728_read_buffer(mte,REG_F_ISTAY,fod.ptr,2);
// pr_info("[%s] Stay current:%d mA\n", __func__,fod.value);
// pr_info("[%s] Clear this flag and the system will ping again\n", __func__,fod.value);
// pr_info("[%s] In case of FOD, there may be metal in the middle, and TX function needs to be turned off\n", __func__,fod.value);
//prize add by lipengpeng 20210507 start
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
// atomic_set(&mte->is_tx_mode,3); //Reverse charging device abnormal, stop reverse charging
#endif
//prize add by lipengpeng 20210507 end
// }
if(val.value & INT_POWER_TRANS){
//prize add by lipengpeng 20210507 start
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
atomic_set(&mte->is_tx_mode,2); //The device is approaching and reverse charging is started
#endif
//prize add by lipengpeng 20210507 end
pr_info("[%s] Charge RX normally\n", __func__);
mte->rxdetect_flag = 1;
}
if(val.value & INT_REMOVE_POWER){
mte->rxdetect_flag = 0;
mte->rxremove_flag = 1;
//prize add by lipengpeng 20210507 start
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
// atomic_set(&mte->is_tx_mode,3); //Keep the device away and stop reverse charging
#endif
//prize add by lipengpeng 20210507 end
pr_info("[%s] Off charge, RX may be removed, or for other reasons\n", __func__);
}
#if 0
if(val.value & INT_CHARGE_STATUS){
vuc eleq;
pr_info("[%s] RX reported the current power\n", __func__);
MT5728_read_buffer(mte,REG_RXCHARGESTATUS,eleq.ptr,2);
if(eleq.value >= 100){
pr_info("[%s] Off charge,Disconnect wireless charging,now!!!\n", __func__);
}
}
if(val.value & INT_TXINIT){
mte->tx_count++;
if(mte->tx_count == 1){
vuc txinit;
MT5728_read_buffer(mte,REG_STABILITY,txinit.ptr,2);
if(txinit.value == 0x5555){
txinit.value = 0x6666;
MT5728_write_buffer(mte,REG_STABILITY,txinit.ptr,2);
pr_info("[%s] TX starts working\n", __func__);
}
}
if(mte->tx_count == 2){
pr_err("[%s] The chip is reset. It may be put on the TX of another home when it is charged reversely\n",__func__);
pr_err("[%s] Turn off TX function\n",__func__);
}
}
#endif
}
scmd.value |= CLEAR_INT;
//---clrintflag
//MT5728_write_buffer(mte, REG_INTCLR, fclr.ptr, 2);
MT5728_write_buffer(mte, REG_INTCLR, fclr.ptr, 2);
pr_info("[%s] write REG_INTCLR : 0x%04x,\n", __func__, fclr.value);
MT5728_write_buffer(mte, REG_CMD, scmd.ptr, 2);
pr_info("[%s] write REG_CMD : 0x%04x,\n", __func__, scmd.value);
//prize add by lipengpeng 20210409 start Modify the problem that the time of closing and recharging exceeds 400ms when USB is inserted
//schedule_delayed_work(&mte->eint_work,100); //Callback check if the interrupt is cleared
schedule_delayed_work(&mte->eint_work,msecs_to_jiffies(100)); //Callback check if the interrupt is cleared
//prize add by lipengpeng 20210409 end
}
EXPORT_SYMBOL(MT5728_irq_handle);
static void MT5728_eint_work(struct work_struct* work) {
MT5728_irq_handle();
}
static void MT5728_add_current_work(struct work_struct* work) {
vuc tcur;
vuc temp;
// MT5728_read_buffer(mte, REG_CURFUNC, temp.ptr,1);
pr_err("[%s] Call back\n",__func__);
if(temp.ptr[0] == 0){
MT5728_read_buffer(mte, REG_IOUT, tcur.ptr,2);
pr_err("[%s] Rx:Iout:%d\n",__func__,tcur.value);
pr_err("[%s] wireless max power :%d\n",__func__,mte->wireless_max_power);
if(mte->wireless_max_power >=10){
int ifit = mte->wireless_max_power *1000 / 9 * 98 / 100;
if(ifit < tcur.value) {
En_Dis_add_current(0xFF);
pr_err("[%s] En_Dis_add_current : DISABLE\n",__func__);
}
}
}else{
pr_err("[%s] It has been disabled\n",__func__);
}
return;
}
static irqreturn_t MT5728_irq(int irq,void * data){
struct MT5728_dev * mt5728 = data;
pr_err("gezi: MT5728_irq---------------\n");
//prize add by lipengpeng 20210409 start Modify the problem that the time of closing and recharging exceeds 400ms when USB is inserted
schedule_delayed_work(&mt5728->eint_work,msecs_to_jiffies(100));
//prize add by lipengpeng 20210409 end
return IRQ_HANDLED;
}
static const struct of_device_id match_table[] = {
{ .compatible = "maxictech,mt5728-30w",},
};
int get_MT5728_status(void){
vuc chipid;
u8 state = 0;
chipid.value = 0;
if(!mt5728_init_done || (mte->charge_protocol == PROTOCOL_UNKNOWN)){
return -1;
}
if(MT5728_read_buffer(mte, MT5728_STATE_ADDR, &state,1) == 0){
pr_err("gezi:%s 0x%x\n",__func__,state);
if(state & 0x01){
return 0;
}
else{
return -1;
}
}
else{
pr_err("gezi:err!!! %s 0x%x\n",__func__,state);
return -1;
}
/*
if((mte->charge_protocol == PROTOCOL_UNKNOWN) || (mte->wireless_max_power <= 0)){
print_curfunc_info();
pr_err("gezi:wireless_charge not exist,return...\n");
return -1;
}
*/
if(MT5728_read_buffer(mte, REG_CHIPID, chipid.ptr,2) == 0){
if(chipid.value == MT5728ID){
pr_err("%s: chipID : %02x%02x chipid.value =0x%04x\n",__func__,chipid.ptr[0],chipid.ptr[1],chipid.value);
return 0;
} else {
pr_err("ID error :%d\n ", chipid.value);
return -3;
}
}
else
{
return -1;
}
}
EXPORT_SYMBOL(get_MT5728_status);
int get_MT5728_private_protocol_state(void)
{
if(!mte){
return 0;
}
return mte->private_protocol_state;
}
EXPORT_SYMBOL(get_MT5728_private_protocol_state);
enum wireless_charge_protocol check_wireless_charge_status (void){
if(get_MT5728_status() != 0)
return PROTOCOL_UNKNOWN;
return mte->charge_protocol;
}
EXPORT_SYMBOL(check_wireless_charge_status);
int reset_mt5728_info(void){
if(!mt5728_init_done){
pr_err("%s not init done!!!\n",__func__);
return 0;
}
mte->wireless_max_power =0;
mte->charge_protocol = PROTOCOL_UNKNOWN;
mte->input_current = 0;
mte->charge_current = 0;
mte->force_swchg = 0;
mte->wireless_connect_over_time = false;
mte->disconnect_cnt = 0;
mte->chg_done = false;
if(mte->private_protocol_state){
mte->private_protocol_state = 0;
turn_on_5728_wpc_vdd(0);
}
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
mt5728_wireless_algo_stop();
#endif
cancel_delayed_work(&mte->mt5728_Private_packet_proc_work);
cancel_delayed_work(&mte->mt5728_pp18_packet_send_work);
cancel_delayed_work(&mte->mt5728_connect_over_time_work);
pr_err("%s\n",__func__);
return 0;
}
EXPORT_SYMBOL(reset_mt5728_info);
int get_wireless_charge_current(struct charger_data *pdata){
pdata->input_current_limit = mte->input_current;
pdata->charging_current_limit = mte->charge_current;
if(!(mte->wireless_connect_over_time)){
if(pdata->input_current_limit > 800000){
pdata->input_current_limit = 800000;
}
if(pdata->charging_current_limit > 800000){
pdata->charging_current_limit = 800000;
}
}
pr_info("[%s] input_current = %d,charge_current = %d,ov:%d\n", __func__,mte->input_current,mte->charge_current,mte->wireless_connect_over_time);
print_curfunc_info();
return 0;
}
EXPORT_SYMBOL(get_wireless_charge_current);
void mt5728_connect_set_over_time(void)
{
mte->wireless_connect_over_time = true;
}
static void mt5728_connect_over_time_work_func(struct work_struct* work)
{
mte->wireless_connect_over_time = true;
}
//static bool eint_working = false;
int power_good_eint_type = IRQ_TYPE_EDGE_FALLING;
/*
static int mt5728_psy_online_changed(int on)
{
int ret = 0;
#if 1
union power_supply_propval propval;
if (mte->psy == NULL){
mte->psy = power_supply_get_by_name("charger");
}
if (!mte->psy) {
pr_err("gezi:%s: get power supply failed\n", __func__);
return -EINVAL;
}
propval.intval = on;
ret = power_supply_set_property(mte->psy, POWER_SUPPLY_PROP_ONLINE, &propval);
if (ret < 0)
pr_err("gezi--%s: psy online fail(%d)\n", __func__, ret);
else
pr_err("gezi:---%s: psy online:%d\n",__func__,on);
#endif
return ret;
}
static int mt5728_psy_chg_type_changed(int on)
{
int ret = 0;
#if 1
union power_supply_propval propval;
if (!mte->psy)
mte->psy = power_supply_get_by_name("charger");
if (!mte->psy) {
pr_err("gezi:%s: get power supply failed\n", __func__);
return -EINVAL;
}
if(on){
propval.intval = NONSTANDARD_CHARGER;
}
else{
propval.intval = CHARGER_UNKNOWN;
}
ret = power_supply_set_property(mte->psy,POWER_SUPPLY_PROP_CHARGE_TYPE,&propval);
if (ret < 0)
pr_err("gezi---%s: psy type failed, ret = %d\n", __func__, ret);
else
pr_err("gezi---%s: chg_type = %d\n", __func__,propval.intval);
#endif
return ret;
}
*/
/*
static void mt5728_connect_check_work_func(struct work_struct* work)
{
//mte->wireless_connect_over_time = true;
enum charger_type chr_type;
int power_good_value = 0;
int vbus = 0;
chr_type = mt_get_charger_type();
power_good_value = gpio_get_value(mte->power_good_gpio);
vbus = battery_get_vbus();
pr_err("gezi[%s]chr_type:%d,power_good:%d,vbus:%d,dis_cnt:%d\n", \
__func__,chr_type,power_good_value,vbus,mte->disconnect_cnt);
if(chr_type == NONSTANDARD_CHARGER && !power_good_value && !vbus){
mte->disconnect_cnt++;
if(mte->disconnect_cnt >= 5){
//mt5728_start_charging(false);
//mt5728_psy_online_changed(0);
//mt5728_psy_chg_type_changed(0);
mte->disconnect_cnt = 0;
return;
}
else{
schedule_delayed_work(&mte->mt5728_connect_check_work,msecs_to_jiffies(1000));
}
}
else{
mte->disconnect_cnt = 0;
}
}
*/
/*
void mt5728_connect_check(void)
{
pr_err("[%s]++\n",__func__);
if (gezi_boot_mode == 8 || gezi_boot_mode == 9){
pr_err("gezi---[%s]power off charge mode,skip!\n",__func__);
return;
}
schedule_delayed_work(&mte->mt5728_connect_check_work,msecs_to_jiffies(800));
}
EXPORT_SYMBOL(mt5728_connect_check);
*/
static int mt5728_turn_off_primary_charge(int off)
{
if (!primary_charger){
primary_charger = get_charger_by_name("primary_chg");
if (!primary_charger) {
pr_err("%s: get primary_chg device failed\n", __func__);
return -ENODEV;
}
}
pr_err("%s++%d\n",__func__,off);
if(off){
charger_dev_enable(primary_charger,false);
}
else{
charger_dev_enable(primary_charger,true);
}
return 0;
}
static void mt5728_pp18_packet_send_work_func(struct work_struct* work)
{
pr_err("[%s]++\n",__func__);
if(battery_get_uisoc() >= 90){
pr_err("[%s]++++++\n",__func__);
mt5728_turn_off_primary_charge(1);
mt5728_send_ask_key();
msleep(500);
mt5728_turn_off_primary_charge(0);
}
mte->wireless_connect_over_time = true;
//schedule_delayed_work(&mte->mt5728_pp18_packet_send_work,msecs_to_jiffies(1000));
}
/*
static void mt5728_power_good_leave_check_work_func(struct work_struct* work)
{
enum charger_type chr_type;
int power_good_value = 0;
chr_type = mt_get_charger_type();
power_good_value = gpio_get_value(mte->power_good_gpio);
pr_err("gezi[%s]----chr_type:%d,power_good_value:%d,check:%d\n",__func__,chr_type,power_good_value,mte->power_good_leave_double_check);
if(chr_type != CHARGER_UNKNOWN && !power_good_value){
mte->power_good_leave_double_check++;
if(mte->power_good_leave_double_check >= 2){
mte->power_good_leave_double_check = 0;
//mt5728_start_charging(false);
//mt5728_psy_online_changed(0);
//mt5728_psy_chg_type_changed(0);
}
else{
schedule_delayed_work(&mte->mt5728_power_good_leave_check_work,msecs_to_jiffies(500));
}
}
else{
mte->power_good_leave_double_check = 0;
}
}
static void mt5728_power_good_eint_work_func(struct work_struct* work)
{
enum charger_type chr_type;
int power_good_value = 0;
chr_type = mt_get_charger_type();
power_good_value = gpio_get_value(mte->power_good_gpio);
pr_err("gezi[%s]----chr_type:%d,power_good_value:%d\n",__func__,chr_type,power_good_value);
if(chr_type == CHARGER_UNKNOWN && power_good_value){
cancel_delayed_work(&mte->mt5728_power_good_leave_check_work);
cancel_delayed_work(&mte->mt5728_connect_check_work);
mte->disconnect_cnt = 0;
mt5728_psy_online_changed(1);
mt5728_psy_chg_type_changed(1);
mt5728_start_charging(true);
}
else if(chr_type != CHARGER_UNKNOWN && !power_good_value){
mte->power_good_leave_double_check = 0;
schedule_delayed_work(&mte->mt5728_power_good_leave_check_work,msecs_to_jiffies(1500));
}
}
*/
static void power_good_eint_work_callback(struct work_struct *work)
{
//if(!eint_working){
// eint_working = true;
//schedule_delayed_work(&mte->mt5728_power_good_eint_work,msecs_to_jiffies(10));
//}
enable_irq(mte->power_good_irq);
}
static irqreturn_t power_good_eint_func(int irq,void *data)
{
if(!mte){
return IRQ_HANDLED;
}
pr_err("gezi---[%s] enter,\n",__func__);
disable_irq_nosync(mte->power_good_irq);
if (power_good_eint_type == IRQ_TYPE_EDGE_RISING)
{
power_good_eint_type = IRQ_TYPE_EDGE_FALLING;
}
else
{
power_good_eint_type = IRQ_TYPE_EDGE_RISING;
}
irq_set_irq_type(mte->power_good_irq, power_good_eint_type);
queue_work(mte->power_good_eint_workqueue, &mte->power_good_eint_work);
return IRQ_HANDLED;
}
/*
static void mt5728_check_charge_state_work_func(struct work_struct* work)
{
//enum charger_type chr_type;
int power_good_value = 0;
//chr_type = mt_get_charger_type();
power_good_value = gpio_get_value(mte->power_good_gpio);
//pr_err("gezi---[%s] enter,\n",__func__);
pr_err("gezi[%s]----chr_type:%d,power_good_value:%d\n",__func__,chr_type,power_good_value);
if (gezi_boot_mode == 8 || gezi_boot_mode == 9){
pr_err("gezi---[%s]power off charge mode,skip!\n",__func__);
return;
}
if(chr_type == CHARGER_UNKNOWN && power_good_value){
//mt5728_psy_online_changed(1);
//mt5728_psy_chg_type_changed(1);
//mt5728_start_charging(true);
}
mte->boot_complete = true;
}
*/
static void mt5728_init_charge_state(void)
{
pr_err("gezi---[%s] enter,\n",__func__);
//schedule_delayed_work(&mte->mt5728_check_charge_state_work,msecs_to_jiffies(10000));
}
static int MT5728_parse_dt(struct i2c_client *client, struct MT5728_dev *mt5728)
{
int ret =0;
/*
mt5728->statu_gpio = of_get_named_gpio(client->dev.of_node, "statu_gpio", 0);
if (mt5728->statu_gpio < 0) {
pr_err("%s: no dc gpio provided\n", __func__);
return -1;
} else {
pr_info("%s: dc gpio provided ok. mt5715->statu_gpio = %d\n", __func__, mt5728->statu_gpio);
devm_gpio_request_one(&client->dev, mt5728->statu_gpio,GPIOF_DIR_IN, "mt5728_statu");
}
*/
mt5728->irq_gpio = of_get_named_gpio(client->dev.of_node, "irq-gpio", 0);
if (mt5728->irq_gpio < 0) {
pr_err("%s: no irq gpio provided.\n", __func__);
return -1;
} else {
pr_info("%s: irq gpio provided ok. mt5715->irq_gpio = %d\n", __func__, mt5728->irq_gpio);
}
ret = of_property_read_u32(client->dev.of_node,"rx_power_capability",&mt5728->rx_power_cap);
if (ret < 0){
mt5728->rx_power_cap = 15;
//return ret;
}
dev_info(&client->dev,"%s: Set rx_power_capability:%d\n",__func__,mt5728->rx_power_cap);
ret = of_property_read_u32(client->dev.of_node,"rx_efficiency",&mt5728->rx_efficiency);
if (ret < 0){
mt5728->rx_efficiency = 98;
//return ret;
}
dev_info(&client->dev,"%s: Set rx_efficiency:%d\n",__func__,mt5728->rx_efficiency);
ret = of_property_read_u32(client->dev.of_node,"one_pin_ctl",&mt5728->one_pin_ctl);
if (ret >= 0){
if (mt5728->one_pin_ctl){
/*
mt5728->otgen_gpio = of_get_named_gpio(client->dev.of_node, "otgen_gpio", 0);
if (gpio_is_valid(mt5728->otgen_gpio)) {
dev_info(&client->dev,"%s: otgen_gpio:%d\n", __func__, mt5728->otgen_gpio);
ret = devm_gpio_request(&client->dev, mt5728->otgen_gpio, "mt5728_otgen");
if (ret < 0) {
dev_err(&client->dev, "%s: otgen_gpio request fail(%d)\n",__func__, ret);
return ret;
}
} else {
dev_err(&client->dev,"get otgen_gpio fail %d\n", mt5728->otgen_gpio);
return -EINVAL;
}
*/
//return 0;
mt5728->one_pin_ctl = 0;
}
}else{
mt5728->one_pin_ctl = 0;
}
/*
mt5728->chipen_gpio = of_get_named_gpio(client->dev.of_node, "chipen_gpio", 0);
if (gpio_is_valid(mt5728->chipen_gpio)) {
dev_info(&client->dev,"%s: chipen_gpio:%d\n", __func__, mt5728->chipen_gpio);
ret = devm_gpio_request(&client->dev, mt5728->chipen_gpio, "sgm2541_en");
if (ret < 0) {
dev_err(&client->dev, "%s: otgen_gpio request fail(%d)\n",__func__, ret);
}
} else {
dev_err(&client->dev,"get otgen_gpio fail %d\n", mt5728->otgen_gpio);
}
*/
mt5728->test_r_gpio = of_get_named_gpio(client->dev.of_node, "test_r_gpio", 0);
if (gpio_is_valid(mt5728->test_r_gpio)) {
dev_info(&client->dev,"%s: test_r_gpio:%d\n", __func__, mt5728->test_r_gpio);
ret = devm_gpio_request(&client->dev, mt5728->test_r_gpio, "sgm2541_test_r");
if (ret < 0) {
dev_err(&client->dev, "%s: test_r_gpio request fail(%d)\n",__func__, ret);
}
} else {
dev_err(&client->dev,"get test_r_gpio fail %d\n", mt5728->test_r_gpio);
}
/*
mt5728->ldoctrl_gpio = of_get_named_gpio(client->dev.of_node, "ldoctrl_gpio", 0);
if (gpio_is_valid(mt5728->ldoctrl_gpio)) {
dev_info(&client->dev,"%s: ldoctrl_gpio:%d\n", __func__, mt5728->ldoctrl_gpio);
ret = devm_gpio_request(&client->dev, mt5728->ldoctrl_gpio, "sgm2541_ldo");
if (ret < 0) {
dev_err(&client->dev, "%s: ldoctrl_gpio request fail(%d)\n",__func__, ret);
}
} else {
dev_err(&client->dev,"get ldoctrl_gpio fail %d\n", mt5728->ldoctrl_gpio);
}
*/
mt5728->otg_5728_ctl.pinctrl_gpios = devm_pinctrl_get(&client->dev);
if (IS_ERR(mt5728->otg_5728_ctl.pinctrl_gpios)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.pinctrl_gpios);
pr_err("%s can't find chg_data pinctrl\n", __func__);
return ret;
}
mt5728->otg_5728_ctl.pins_default = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "default");
if (IS_ERR(mt5728->otg_5728_ctl.pins_default)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.pins_default);
pr_err("%s can't find chg_data pinctrl default\n", __func__);
/* return ret; */
}
/*
mt5728->otg_5728_ctl.charger_otg_off = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "charger_otg_off");
if (IS_ERR(mt5728->otg_5728_ctl.charger_otg_off)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.charger_otg_off);
pr_err("%s can't find chg_data pinctrl otg high\n", __func__);
return ret;
}
mt5728->otg_5728_ctl.charger_otg_on = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "charger_otg_on");
if (IS_ERR(mt5728->otg_5728_ctl.charger_otg_on)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.charger_otg_on);
pr_err("%s can't find chg_data pinctrl otg low\n", __func__);
return ret;
}
*/
mt5728->otg_5728_ctl.wireless_5728_off = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "wireless_5728_off");
if (IS_ERR(mt5728->otg_5728_ctl.wireless_5728_off)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.wireless_5728_off);
pr_err("%s can't find chg_data pinctrl wireless_5728_off\n", __func__);
return ret;
}
mt5728->otg_5728_ctl.wireless_5728_on = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "wireless_5728_on");
if (IS_ERR(mt5728->otg_5728_ctl.wireless_5728_on)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.wireless_5728_on);
pr_err("%s can't find chg_data pinctrl wireless_5728_on\n", __func__);
return ret;
}
mt5728->otg_5728_ctl.mt5728_wpc_vdd_on = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "mt5728_wpc_vdd_on");
if (IS_ERR(mt5728->otg_5728_ctl.mt5728_wpc_vdd_on)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.mt5728_wpc_vdd_on);
pr_err("%s can't find chg_data pinctrl mt5728_wpc_vdd_on\n", __func__);
return ret;
}
mt5728->otg_5728_ctl.mt5728_wpc_vdd_off = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "mt5728_wpc_vdd_off");
if (IS_ERR(mt5728->otg_5728_ctl.mt5728_wpc_vdd_off)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.mt5728_wpc_vdd_off);
pr_err("%s can't find chg_data pinctrl mt5728_wpc_vdd_off\n", __func__);
return ret;
}
/*
mt5728->usb_switch = of_get_named_gpio(client->dev.of_node, "usb_switch", 0);
if (gpio_is_valid(mt5728->usb_switch)) {
dev_info(&client->dev,"%s: usb_switch:%d\n", __func__, mt5728->usb_switch);
ret = devm_gpio_request(&client->dev, mt5728->usb_switch, "usb_switch");
if (ret < 0) {
dev_err(&client->dev, "%s: usb_switch request fail(%d)\n",__func__, ret);
}
} else {
dev_err(&client->dev,"get usb_switch fail %d\n", mt5728->usb_switch);
return ret;
}
*/
mt5728->power_good_gpio = of_get_named_gpio(client->dev.of_node, "power_good_gpio", 0);
if (gpio_is_valid(mt5728->power_good_gpio)) {
dev_info(&client->dev,"%s: power_good_gpio:%d\n", __func__, mt5728->power_good_gpio);
ret = devm_gpio_request(&client->dev, mt5728->power_good_gpio, "power_good_gpio");
if (ret < 0) {
dev_err(&client->dev, "%s: power_good_gpio request fail(%d)\n",__func__, ret);
}
else{
gpio_direction_input(mt5728->power_good_gpio);
mt5728->power_good_irq = gpio_to_irq(mt5728->power_good_gpio);
ret = request_irq(mt5728->power_good_irq, power_good_eint_func,IRQ_TYPE_EDGE_RISING, "power_good_default", NULL);
if (ret > 0){
dev_err(&client->dev, "%s: request_irq fail(%d)\n",__func__, ret);
}
else {
dev_err(&client->dev, "%s: request_irq success(%d)\n",__func__, ret);
}
enable_irq_wake(mt5728->power_good_irq);
}
}
else {
dev_err(&client->dev,"---get power_good_gpio fail %d\n", mt5728->power_good_gpio);
return ret;
}
//prize add by lipengpeng 20210308 start
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
mt5728->otg_5728_ctl.charger_otg_mode_on = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "charger_otg_mode_on");
if (IS_ERR(mt5728->otg_5728_ctl.charger_otg_mode_on)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.charger_otg_mode_on);
pr_err("%s can't find chg_data pinctrl charger_otg_mode_on\n", __func__);
return ret;
}
mt5728->otg_5728_ctl.charger_otg_mode_off = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "charger_otg_mode_off");
if (IS_ERR(mt5728->otg_5728_ctl.charger_otg_mode_off)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.charger_otg_mode_off);
pr_err("%s can't find chg_data pinctrl charger_otg_mode_off\n", __func__);
return ret;
}
//prize add by lipengpeng 20210308 end
//prize add by lipengpeng 20210416 start BPI_BUS4 GPIO90
/* mt5728->otg_5728_ctl.test_gpio_on = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "test_gpio");
if (IS_ERR(mt5728->otg_5728_ctl.test_gpio_on)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.test_gpio_on);
pr_err("%s can't find chg_data pinctrl test_gpio_on\n", __func__);
//return ret;
}
mt5728->otg_5728_ctl.test_gpio_off = pinctrl_lookup_state(mt5728->otg_5728_ctl.pinctrl_gpios, "test_off");
if (IS_ERR(mt5728->otg_5728_ctl.test_gpio_off)) {
ret = PTR_ERR(mt5728->otg_5728_ctl.test_gpio_off);
pr_err("%s can't find chg_data pinctrl test_gpio_off\n", __func__);
//return ret;
}*/
#endif
//prize add by lipengpeng 20210416 start BPI_BUS4 GPIO90
mt5728->otg_5728_ctl.gpio_otg_prepare = true;
return 0;
}
int turn_off_5728(int en){
int ret =0;
if(!mt5728_init_done){
return 0;
}
if (mte->one_pin_ctl){
if (gpio_is_valid(mte->otgen_gpio)){
if (en){
gpio_direction_output(mte->otgen_gpio,1);
}else{
gpio_direction_output(mte->otgen_gpio,0);
}
}
return ret;
}
if (mte->otg_5728_ctl.gpio_otg_prepare) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_off); //high
printk("%s: set W_OTG_EN2 to hight %d\n", __func__,gpio_get_value(mte->test_r_gpio));
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_on);//low
printk("%s: set W_OTG_EN2 to low %d\n", __func__,gpio_get_value(mte->test_r_gpio));
ret =0;
}
}
else {
printk("%s:, error, gpio otg not prepared\n", __func__);
ret =-1;
}
return ret;
}
EXPORT_SYMBOL(turn_off_5728);
int turn_on_5728_wpc_vdd(int en)
{
int ret =0;
if(mte->otg_5728_ctl.gpio_otg_prepare)
{
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.mt5728_wpc_vdd_on); //high
printk("%s: set mt5728_wpc_vdd_on to hight\n", __func__);
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.mt5728_wpc_vdd_off);//low
printk("%s: set mt5728_wpc_vdd_on to low\n", __func__);
ret =0;
}
}
else {
printk("%s:, error, gpio otg not prepared\n", __func__);
ret =-1;
}
return ret;
}
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
/**<2A>˳<EFBFBD>TXģʽ OD7<44><37><EFBFBD>ͣ<EFBFBD>OD5<44><35><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>txģʽ<C4A3><CABD>OD7<44><37><EFBFBD>ߣ<EFBFBD>OD5<44><35><EFBFBD><EFBFBD>*/
int turn_on_otg_charge_mode(int en){
int ret =0;
if (mte->otg_5728_ctl.charger_otg_mode_on) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.charger_otg_mode_on);//
printk("%s: set charger_otg_mode_on to hight\n", __func__);
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.charger_otg_mode_off);//
printk("%s: set charger_otg_mode_on to low\n", __func__);
ret =0;
}
}
else {
printk("%s:, error, gpio charger_otg_mode_on not prepared\n", __func__);
ret =-1;
}
return ret;
}
EXPORT_SYMBOL(turn_on_otg_charge_mode);
/*
int turn_on_rever_5725(int en){
int ret =0;
if (mte->one_pin_ctl){
if (gpio_is_valid(mte->otgen_gpio)){
if (en){
gpio_direction_output(mte->otgen_gpio,1); //GPOD7 high
}else{
gpio_direction_output(mte->otgen_gpio,0);//GPOD7 low
}
}
return ret;
}
if (mte->otg_5728_ctl.gpio_otg_prepare) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_on);//GPOD5 low
printk("%s: set W_OTG_EN2 to hight\n", __func__,);
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_off);//GPOD5 high
printk("%s: set W_OTG_EN2 to low\n", __func__);
ret =0;
}
}
else {
printk("%s:, error, gpio otg not prepared\n", __func__);
ret =-1;
}
return ret;
}
EXPORT_SYMBOL(turn_on_rever_5725);
*/
/**<2A>˳<EFBFBD>TXģʽ OD7<44><37><EFBFBD>ͣ<EFBFBD>OD5<44><35><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>txģʽ<C4A3><CABD>OD7<44><37><EFBFBD>ߣ<EFBFBD>OD5<44><35><EFBFBD><EFBFBD>*/
/*
int turn_off_rever_5725(int en){
int ret =0;
if (mte->one_pin_ctl){
if (gpio_is_valid(mte->otgen_gpio)){
if (en){
gpio_direction_output(mte->otgen_gpio,1); //GPOD7 high
}else{
gpio_direction_output(mte->otgen_gpio,0);//GPOD7 low
}
}
return ret;
}
if (mte->otg_5728_ctl.gpio_otg_prepare) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_off);//GPOD5 high
printk("%s: set W_OTG_EN2 to hight %d\n", __func__,gpio_get_value(mte->statu_gpio));
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_on);//GPOD5 low
printk("%s: set W_OTG_EN2 to low %d\n", __func__,gpio_get_value(mte->statu_gpio));
ret =0;
}
}
else {
printk("%s:, error, gpio otg not prepared\n", __func__);
ret =-1;
}
return ret;
}
EXPORT_SYMBOL(turn_off_rever_5725);
*/
#endif
/*
int set_otg_gpio(int en){
int ret =0;
if (mte->one_pin_ctl){
if (gpio_is_valid(mte->otgen_gpio)){
if (en){
gpio_direction_output(mte->otgen_gpio,1);
}else{
gpio_direction_output(mte->otgen_gpio,0);
}
}
return ret;
}
if (mte->otg_5728_ctl.gpio_otg_prepare) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.charger_otg_on);
printk("%s: set w_otg_en PIN to high %d \n", __func__,gpio_get_value(mte->otgen_gpio));
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.charger_otg_off);
printk("%s: set w_otg_en PIN to low %d \n", __func__,gpio_get_value(mte->otgen_gpio));
ret =0;
}
}
else {
printk("%s:, error, gpio otg not prepared\n", __func__);
ret =-1;
}
return ret;
}
EXPORT_SYMBOL(set_otg_gpio);
*/
int set_test_r_gpio(int en)
{
int ret =0;
if (mte->otg_5728_ctl.gpio_otg_prepare) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_off);//GPOD5 high
printk("%s: set set_test_r_gpio to hight\n", __func__);
ret = 0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.wireless_5728_on);//GPOD5 low
printk("%s: set set_test_r_gpio to low\n", __func__);
ret = 0;
}
}
return ret;
}
EXPORT_SYMBOL(set_test_r_gpio);
//prize add by lipengpeng 20210408 start
//prize add by lipengpeng 20210416 start BPI_BUS4 GPIO90
//#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
/*
int test_gpio(int en){
int ret =0;
if (mte->otg_5728_ctl.gpio_otg_prepare) {
if (en) {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.test_gpio_on);
printk("%s: set test gpio to hight\n", __func__);
ret =0;
}
else {
pinctrl_select_state(mte->otg_5728_ctl.pinctrl_gpios, mte->otg_5728_ctl.test_gpio_off);
printk("%s: set test gpio to low\n", __func__);
ret =0;
}
}
return ret;
}
EXPORT_SYMBOL(test_gpio);
//#endif
*/
static int MT5728_probe(struct i2c_client *client, const struct i2c_device_id *id) {
struct MT5728_dev *chip;
int irq_flags = 0;
int rc = 0,ret = 0;
vuc protocol;
pr_err("MT5728 probe.\n");
chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
if (!chip){
return -ENOMEM;
}
chip->client = client;
chip->dev = &client->dev;
pr_err("MT5728 chip.\n");
//prize add by lipengpeng 20220716 start
chip->regmap = devm_regmap_init_i2c(client, &MT5728_regmap_config);
//prize add by lipengpeng 20220716 start
if (!chip->regmap) {
pr_err("parent regmap is missing\n");
return -EINVAL;
}
pr_err("MT5728 regmap.\n");
chip->bus.read = MT5728_read;
chip->bus.write = MT5728_write;
chip->bus.read_buf = MT5728_read_buffer;
chip->bus.write_buf = MT5728_write_buffer;
device_init_wakeup(chip->dev, true);
ret = sysfs_create_group(&client->dev.kobj, &mt5728_sysfs_group);
if (ret){
pr_err("MT5728 sysfs_create_group fail!\n\n");
}
pr_err("MT5728 probed successfully\n");
mte = chip;
mte->wireless_max_power = 0;
mte->otg_5728_ctl.gpio_otg_prepare = false;
mte->charge_protocol = PROTOCOL_UNKNOWN;
mte->input_current = 0;
mte->charge_current = 0;
INIT_DELAYED_WORK(&chip->eint_work, MT5728_eint_work);
INIT_DELAYED_WORK(&chip->add_current_work, MT5728_add_current_work);
INIT_DELAYED_WORK(&chip->charger_work, mt5728_charger_work_func);
INIT_DELAYED_WORK(&chip->reverse_charge_work, mt5728_reverse_work_func);
INIT_DELAYED_WORK(&chip->fwcheck_work, mt5728_fwcheck_work_func);
INIT_DELAYED_WORK(&chip->mt5728_Private_packet_proc_work, mt5728_Private_packet_proc_work_func);
//INIT_DELAYED_WORK(&chip->mt5728_power_good_eint_work, mt5728_power_good_eint_work_func);
//INIT_DELAYED_WORK(&chip->mt5728_check_charge_state_work, mt5728_check_charge_state_work_func);
INIT_DELAYED_WORK(&chip->mt5728_pp18_packet_send_work, mt5728_pp18_packet_send_work_func);
INIT_DELAYED_WORK(&chip->mt5728_tx_enable_work, mt5728_tx_enable_work_func);
INIT_DELAYED_WORK(&chip->mt5728_tx_disable_work, mt5728_tx_disable_work_func);
//INIT_DELAYED_WORK(&chip->mt5728_power_good_leave_check_work, mt5728_power_good_leave_check_work_func);
INIT_DELAYED_WORK(&chip->mt5728_connect_over_time_work, mt5728_connect_over_time_work_func);
//INIT_DELAYED_WORK(&chip->mt5728_connect_check_work,mt5728_connect_check_work_func);
INIT_DELAYED_WORK(&chip->mt5728_fw_update_work, mt5728_fw_update_work_func);
chip->power_good_eint_workqueue = create_singlethread_workqueue("power_good_eint");
INIT_WORK(&chip->power_good_eint_work, power_good_eint_work_callback);
rc = MT5728_parse_dt(client, chip);
if (rc) {
pr_err("%s: failed to parse device tree node\n", __func__);
chip->statu_gpio = -1;
chip->irq_gpio = -1;
}
protocol.value =0;
//if(gpio_get_value(mte->statu_gpio)){
//MT5728_read_buffer(mte, REG_CURFUNC, protocol.ptr,1);
pr_err("%s: protocol read 1 : %02x%02x protocol.value =0x%04x protocol.value =%d\n",__func__,protocol.ptr[0],protocol.ptr[1],protocol.value,protocol.value);
//}
if (gpio_is_valid(chip->irq_gpio)) {
rc = devm_gpio_request_one(&client->dev, chip->irq_gpio,
GPIOF_DIR_IN, "mt5728_int");
if (rc) {
pr_err("%s: irq_gpio request failed\n", __func__);
goto err;
}
irq_flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
rc = devm_request_threaded_irq(&client->dev, gpio_to_irq(chip->irq_gpio),
NULL, MT5728_irq, irq_flags, "mt5728", chip);
if (rc != 0) {
pr_err("failed to request IRQ %d: %d\n", gpio_to_irq(chip->irq_gpio), rc);
goto err;
}
pr_err("sucess to request IRQ %d: %d\n", gpio_to_irq(chip->irq_gpio), rc);
enable_irq_wake(gpio_to_irq(chip->irq_gpio));
//start add by sunshuai
//if(!(gpio_get_value(mte->irq_gpio))){
pr_err("%s The interruption has come \n", __func__);
MT5728_irq_handle();
//}
//end add by sunshuai
} else {
pr_info("%s skipping IRQ registration\n", __func__);
}
//prize add by lpp 20210308 start Get whether the device is close when the mobile phone is in a backcharging state
//#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
rc = sysfs_create_link(kernel_kobj,&client->dev.kobj,"wirelessrx");
if (rc){
pr_err(KERN_ERR"mt5728 sysfs_create_link fail\n");
}
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
rc = device_create_file(&client->dev, &dev_attr_enabletx);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_enabletx)\n");
}
rc = device_create_file(&client->dev, &dev_attr_gettxflag);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_gettxflag)\n");
}
#endif
/*
rc = device_create_file(&client->dev, &dev_attr_usb_switch);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_usb_switch)\n");
}
*/
//prize add by lipengpeng 20220623 start
rc = device_create_file(&client->dev, &dev_attr_wireless_connect);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_wireless_connect)\n");
}
rc = device_create_file(&client->dev, &dev_attr_wireless_connect_before);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_wireless_connect_before)\n");
}
rc = device_create_file(&client->dev, &dev_attr_power_good_gpio);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_power_good_gpio)\n");
}
rc = device_create_file(&client->dev, &dev_attr_private_protocol_state);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_private_protocol_state)\n");
}
rc = device_create_file(&client->dev, &dev_attr_fw_update);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_fw_update)\n");
}
rc = device_create_file(&client->dev, &dev_attr_fw_ver);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_fw_ver)\n");
}
rc = device_create_file(&client->dev, &dev_attr_crcvalue);
if (rc){
pr_err(KERN_ERR"mt5728 failed device_create_file(dev_attr_crcvalue)\n");
}
//prize add by lipengpeng 20220623 end
//#endif
//prize add by lpp 20210308 end Get whether the device is close when the mobile phone is in a backcharging state
//prize add by lipengpeng 20210408 start chipen_gpio status
if (gpio_is_valid(mte->chipen_gpio)) {
gpio_direction_output(mte->chipen_gpio, 0); //sgm2541 auto mode
}
//prize add by lipengpeng 20210408 start chipen_gpio status
i2c_set_clientdata(client,chip);
#if IS_ENABLED(CONFIG_PRIZE_MT5728_SUPPORT_40W)
mt5728_40w_init_done = mt5728_wireless_charge_40w_init(&client->dev);
if(mt5728_40w_init_done <= 0){
pr_err("mt5728 40w init fail(%d)\n",mt5728_40w_init_done);
}
#endif
mt5728_init_charge_state();
mt5728_init_done = 1;
if(cc_conect_state){
turn_off_5728(1);
}
pr_info("%s probe done\n", __func__);
return rc;
err:
devm_kfree(&client->dev, chip);
return rc;
}
static int MT5728_remove(struct i2c_client *client) {
sysfs_remove_group(&client->dev.kobj, &mt5728_sysfs_group);
//prize add by lpp 20190821 start
//#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
sysfs_remove_link(kernel_kobj,"wirelessrx");
//prize add by lpp 20190821 start
device_remove_file(&client->dev, &dev_attr_wireless_connect);
//prize add by lpp 20190821 end
#if defined (CONFIG_PRIZE_REVERE_CHARGING_MODE)
device_remove_file(&client->dev, &dev_attr_enabletx);
device_remove_file(&client->dev, &dev_attr_gettxflag);
#endif
//device_remove_file(&client->dev, &dev_attr_disabletx);
//#endif
//prize add by lpp 20190821 end
if (gpio_is_valid(mte->irq_gpio)){
devm_gpio_free(&client->dev, mte->irq_gpio);
}
/*
if (gpio_is_valid(mte->statu_gpio)){
devm_gpio_free(&client->dev, mte->statu_gpio);
}
*/
if (mte->one_pin_ctl){
if (gpio_is_valid(mte->otgen_gpio)){
devm_gpio_free(&client->dev,mte->otgen_gpio);
}
}
return 0;
}
static void MT5728_shutdown(struct i2c_client *client)
{
pr_err("gezi----%s---%d\n",__func__,__LINE__);
turn_off_5728(1);
//msleep(2);
//turn_off_5728(0);
if(revere_mode){
pr_err("gezi----%s---%d\n",__func__,__LINE__);
mt_vbus_revere_off();
mtk_set_sc8571_otg(0);
turn_on_otg_charge_mode(0);
}
}
/*
static const struct i2c_device_id MT5728_dev_id[] = {
{"MT5728_receiver", 0},
{},
};
MODULE_DEVICE_TABLE(i2c, MT5728_dev_id);
*/
static struct i2c_driver MT5728_driver = {
.driver = {
.name = DEVICE_NAME,
.owner = THIS_MODULE,
.of_match_table = match_table,
},
.probe = MT5728_probe,
.remove = MT5728_remove,
// .id_table = MT5728_dev_id,
.shutdown = MT5728_shutdown,
};
int mt5728_wireless_init(void)
{
int ret = 0;
printk("mt5728 wireless driver init start");
ret = i2c_add_driver(&MT5728_driver);
if ( ret != 0 ) {
printk("mt5728 wireless driver init failed!");
}
printk("mt5728 wireless driver init end");
return ret;
}
EXPORT_SYMBOL(mt5728_wireless_init);
/*
//prize add by lipengpeng 20220609 start
static int __init mt5728_wireless_init(void)
{
int ret = 0;
printk("mt5728 wireless driver init start");
ret = i2c_add_driver(&MT5728_driver);
if ( ret != 0 ) {
printk("mt5728 wireless driver init failed!");
}
printk("mt5728 wireless driver init end");
return ret;
}
static void __exit mt5728_wireless_exit(void)
{
i2c_del_driver(&MT5728_driver);
}
late_initcall_sync(mt5728_wireless_init);
module_exit(mt5728_wireless_exit);
MODULE_AUTHOR("gezi@szprize.com");
MODULE_DESCRIPTION("MT5728 Wireless Power Receiver");
MODULE_LICENSE("GPL v2");
*/