wlc:add feature supporting for Moto 50W dock in WLC driver

The feature of Moto 50w dock requests some file points from wlc driver,
so we should impleamnt them.

Change-Id: I265756f9dd2c4ab06b8114641513c1013b42dd54
Reviewed-on: https://gerrit.mot.com/2355232
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Huosheng Liao <liaohs@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
weiweij 2022-08-05 14:30:13 +08:00 • committed by Wei Wei
commit 3291622632
2 changed files with 232 additions and 13 deletions

View file

@ -76,8 +76,9 @@
#define CPS4019_CHIP_ID 0x4019
#define CPS4019_WORK_VOL 2700000 //mV
#define CPS4019_DEFAULT_POWER 5//5W, unit w
#define CPS4019_PPP_DATA_SIZE 7
#define CPS4019_PPP_DATA_SIZE 8
#define cps_wls_log(num, fmt, args...) \
do { \
@ -139,6 +140,14 @@ struct cps_wls_chrg_chip {
const char *main_charger_name;
struct charger_device *main_chg_dev;
bool is_factory_mode;
bool is_charger_full;
int op_mode;
int fan_speed;
int light_level;
int wlc_status;
/*fw relative*/
const char *wls_fw_name;
int fw_ver_major;
@ -165,6 +174,7 @@ typedef enum
CPS_REG_ADC_VRECT,
CPS_REG_ADC_IOUT,
CPS_REG_ADC_DIE_TEMP,
CPS_REG_PRO_SET,
CPS_REG_PPP_HEADER,
CPS_REG_PPP_CMD,
CPS_REG_PPP_DATA,
@ -194,15 +204,53 @@ cps_reg_s cps_reg_cfg[CPS_REG_MAX] = {
{CPS_REG_ADC_VRECT, 2, 0x0019},
{CPS_REG_ADC_IOUT, 2, 0x001B},
{CPS_REG_ADC_DIE_TEMP, 2, 0x001D},
{CPS_REG_PRO_SET, 2, 0x0068},
{CPS_REG_PPP_HEADER, 2, 0x0025},
{CPS_REG_PPP_CMD, 2, 0x0026},
{CPS_REG_PPP_DATA, 2, 0x0028}
{CPS_REG_PPP_DATA, 2, 0x0027}
};
typedef enum
{
WLC_DISCONNECTED,
WLC_CONNECTED,
WLC_TX_TYPE_CHANGED,
WLC_TX_POWER_CHANGED,
}wlc_status;
typedef enum {
MMI_WLC_NONE,
MMI_WLC_BPP,
MMI_WLC_EPP,
MMI_WLC_MOTO,
} mmi_wlc_type;
typedef enum {
MMI_DOCK_LIGHT_OFF = 0x10,
MMI_DOCK_LIGHT_ON = 0x20,
MMI_DOCK_LIGHT_BREATH_2S = 0x30,
MMI_DOCK_LIGHT_BREATH_4S = 0x40,
MMI_DOCK_LIGHT_DEFAULT = MMI_DOCK_LIGHT_BREATH_4S,
} mmi_dock_light_ctrl;
/* value = fan speed / 100 */
typedef enum {
MMI_DOCK_FAN_SPEED_OFF= 0,
MMI_DOCK_FAN_SPEED_LOW = 20,//2000
MMI_DOCK_FAN_SPEED_HIGH = 60,//6000
MMI_DOCK_FAN_DEFAULT = MMI_DOCK_FAN_SPEED_HIGH,
} mmi_dock_fan_speed;
typedef enum {
MMI_DOCK_LIGHT_INDEX = 0,
MMI_DOCK_FAN_INDEX =1,
} mmi_dock_light_fan_index;
/*define MMI CMD enum*/
typedef enum
{
MMI_CMD_CHARGE_FULL,
MMI_CMD_FAN_LIGHT,
MMI_CMD_MAX
}mmi_cmd_e;
@ -214,9 +262,12 @@ typedef struct
uint32_t len;
}mmi_cmd_s;
#define MMI_WLC_DOCK_CMD_LEN 2
mmi_cmd_s mmi_cmd_cfg[MMI_CMD_MAX] = {
/* cmd_header cmd_cmd cmd_data cmd_len */
{0x5, 0x64, {0}, 0},//MMI_CMD_CHARGE_FULL
{0x38, 0x05, {0}, MMI_WLC_DOCK_CMD_LEN},//MMI_CMD_FAN
};
//-------------------I2C APT start--------------------
@ -244,6 +295,8 @@ static int cps_wls_get_die_tmp(void);
static int cps_wls_set_rx_vout_target(int value);
static int cps_wls_set_rx_ocp_threshold(int value);
static int cps_wls_set_status(int status);
static int cps_wls_read_word_addr32(int reg)
{
int ret;
@ -398,7 +451,7 @@ static int cps_wls_send_ppp_cmd(int header, int cmd, int *data, int len)
if (len > 0) {
cps_reg = (cps_reg_s*)(&cps_reg_cfg[CPS_REG_PPP_DATA]);
for(i = 0; i < len; i++) {
ret = cps_wls_write_reg(cps_reg->reg_addr, data[i], cps_reg->reg_bytes_len);
ret = cps_wls_write_reg(cps_reg->reg_addr + i, data[i], cps_reg->reg_bytes_len);
if(ret == CPS_WLS_FAIL)
goto send_fail;
}
@ -1249,6 +1302,51 @@ static int cps_wls_set_rx_ocp_threshold(int value)
return cps_wls_write_reg(cps_reg->reg_addr, value_temp, (int)cps_reg->reg_bytes_len);
}
static int cps_wls_get_op_mode(void)
{
cps_reg_s *cps_reg;
cps_reg = (cps_reg_s*)(&cps_reg_cfg[CPS_REG_PRO_SET]);
return cps_wls_read_reg((int)cps_reg->reg_addr, (int)cps_reg->reg_bytes_len);
}
static int cps_wls_wlc_update_light_fan(void)
{
mmi_cmd_s* mmi_cmd_p = &mmi_cmd_cfg[MMI_CMD_FAN_LIGHT];
if (chip->is_factory_mode) {
cps_wls_log(CPS_LOG_ERR, "[%s] factory mode, skip\n", __func__);
return 0;
}
if (chip->is_charger_full) {
mmi_cmd_p->data[MMI_DOCK_LIGHT_INDEX] = MMI_DOCK_LIGHT_ON;
mmi_cmd_p->data[MMI_DOCK_FAN_INDEX] = MMI_DOCK_FAN_SPEED_OFF;
} else {
if (chip->fan_speed == 0)
mmi_cmd_p->data[MMI_DOCK_FAN_INDEX] = MMI_DOCK_FAN_SPEED_LOW;
else
mmi_cmd_p->data[MMI_DOCK_FAN_INDEX] = MMI_DOCK_FAN_SPEED_HIGH;
if (chip->light_level == 0)
mmi_cmd_p->data[MMI_DOCK_LIGHT_INDEX] = MMI_DOCK_LIGHT_OFF;
else
mmi_cmd_p->data[MMI_DOCK_LIGHT_INDEX] = MMI_DOCK_LIGHT_DEFAULT;
}
cps_wls_send_ppp_cmd(mmi_cmd_p->header,
mmi_cmd_p->cmd,
mmi_cmd_p->data,
mmi_cmd_p->len);
cps_wls_log(CPS_LOG_ERR, " CPS_WLS: QI set fan/light, WLS_WLC_FAN_SPEED %d "
"CPS_RX_CHRG_FULL %d, WLS_WLC_LIGHT %d",
chip->fan_speed, chip->is_charger_full, chip->light_level);
cps_wls_log(CPS_LOG_ERR, " CPS_WLS: QI set fan/light, ight 0x%x, fan 0x%x",
mmi_cmd_p->data[MMI_DOCK_LIGHT_INDEX], mmi_cmd_p->data[MMI_DOCK_FAN_INDEX]);
return 0;
}
static int cps_wls_charger_notify_full(void)
{
mmi_cmd_s* mmi_cmd_p;
@ -1260,12 +1358,17 @@ static int cps_wls_charger_notify_full(void)
}
cps_wls_log(CPS_LOG_DEBG, "[%s] soc = %d.\n", __func__, data.intval);
if (data.intval != 100)
if (data.intval != 100) {
chip->is_charger_full = false;
return CPS_WLS_FAIL;
}
chip->is_charger_full = true;
/*get vbus status first*/
cps_check_power(&low_power_flag);
if (low_power_flag) {
cps_wls_set_status(WLC_DISCONNECTED);
return CPS_WLS_FAIL;
}
@ -1273,15 +1376,41 @@ static int cps_wls_charger_notify_full(void)
return CPS_WLS_FAIL;
}
mmi_cmd_p = &mmi_cmd_cfg[MMI_CMD_CHARGE_FULL];
cps_wls_send_ppp_cmd(mmi_cmd_p->header,
mmi_cmd_p->cmd,
mmi_cmd_p->data,
mmi_cmd_p->len);
if (chip->op_mode == MMI_WLC_MOTO) {
cps_wls_wlc_update_light_fan();
} else {
mmi_cmd_p = &mmi_cmd_cfg[MMI_CMD_CHARGE_FULL];
cps_wls_send_ppp_cmd(mmi_cmd_p->header,
mmi_cmd_p->cmd,
mmi_cmd_p->data,
mmi_cmd_p->len);
}
return CPS_WLS_SUCCESS;
}
static int cps_wls_notify_st_changed(void)
{
static int pre_status = -1;
if (pre_status != chip->wlc_status) {
cps_wls_log(CPS_LOG_DEBG,"%s st change %d -> %d\n",__func__, pre_status, chip->wlc_status);
pre_status = chip->wlc_status;
sysfs_notify(&chip->wl_psy->dev.parent->kobj, NULL, "wlc_st_changed");
}
return 0;
}
static int cps_wls_set_status(int status)
{
chip->wlc_status = status;
if (status == WLC_DISCONNECTED)
chip->op_mode = MMI_WLC_NONE;
cps_wls_notify_st_changed();
return 0;
}
//------------------------------IRQ Handler-----------------------------------
static int cps_wls_set_int_enable(void)
{
@ -1321,8 +1450,20 @@ static int cps_wls_irq_process(int int_flag)
cps_wls_set_int_enable();
}
if(int_flag & INT_VOUT_STATE) {
cps_wls_set_status(WLC_CONNECTED);
}
/*for 50w dock*/
if ((int_flag & INT_HS_OK) || (int_flag & INT_HS_FAIL)) {
chip->op_mode = cps_wls_get_op_mode();
cps_wls_log(CPS_LOG_DEBG, "[%s] op_mode %d\n", __func__, chip->op_mode);
if (chip->op_mode == MMI_WLC_MOTO) {
cps_wls_set_status(WLC_TX_TYPE_CHANGED);
}
cps_wls_charger_notify_full();
}
//if(int_flag & INT_DATA_STORE){}
//if(int_flag & INT_AC_MIS_DET){}
@ -1388,6 +1529,7 @@ static int cps_wls_chrg_get_property(struct power_supply *psy,
/*get vbus status first*/
cps_check_power(&low_power_flag);
if (low_power_flag) {
cps_wls_set_status(WLC_DISCONNECTED);
val->intval = 0;
return ret;
}
@ -1497,7 +1639,7 @@ static ssize_t store_erase_fw(struct device *dev,
int tmp;
/*Only work in factory mode*/
if (!mmi_is_factory_mode())
if (!chip->is_factory_mode)
return count;
tmp = simple_strtoul(buf, NULL, 0);
@ -1606,6 +1748,70 @@ static ssize_t store_usb_keep_on(struct device *dev,
}
static DEVICE_ATTR(usb_keep_on, 0220, NULL, store_usb_keep_on);
static ssize_t show_wlc_fan_speed(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, " %d\n", chip->fan_speed);
}
static ssize_t store_wlc_fan_speed(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
if (chip->op_mode != MMI_WLC_MOTO) {
cps_wls_log(CPS_LOG_ERR, "[%s] not moto 50w dock %d, skip\n", __func__ , chip->op_mode);
return count;
}
chip->fan_speed = simple_strtoul(buf, NULL, 0);
cps_wls_wlc_update_light_fan();
return count;
}
static DEVICE_ATTR(wlc_fan_speed, S_IRUGO|S_IWUSR, show_wlc_fan_speed, store_wlc_fan_speed);
static ssize_t show_wlc_light_ctl(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, " %d\n", chip->light_level);
}
static ssize_t store_wlc_light_ctl(struct device *dev,
struct device_attribute *attr,
const char *buf,
size_t count)
{
if (chip->op_mode != MMI_WLC_MOTO) {
cps_wls_log(CPS_LOG_ERR, "[%s] not moto 50w dock %d, skip\n", __func__ , chip->op_mode);
return count;
}
chip->light_level = simple_strtoul(buf, NULL, 0);
cps_wls_wlc_update_light_fan();
return count;
}
static DEVICE_ATTR(wlc_light_ctl, S_IRUGO|S_IWUSR, show_wlc_light_ctl, store_wlc_light_ctl);
static ssize_t show_wlc_tx_power(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", CPS4019_DEFAULT_POWER);
}
static DEVICE_ATTR(wlc_tx_power, 0444, show_wlc_tx_power, NULL);
static ssize_t show_wlc_tx_type(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", chip->op_mode);
}
static DEVICE_ATTR(wlc_tx_type, 0444, show_wlc_tx_type, NULL);
static ssize_t show_wlc_st_changed(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%d\n", chip->wlc_status);
}
static DEVICE_ATTR(wlc_st_changed, S_IRUGO, show_wlc_st_changed, NULL);
static ssize_t store_ppp_cmd(struct device *dev,
struct device_attribute *attr,
const char *buf,
@ -1651,6 +1857,13 @@ static void cps_wls_create_device_node(struct device *dev)
device_create_file(dev, &dev_attr_set_ocp_thres);
device_create_file(dev, &dev_attr_usb_keep_on);
device_create_file(dev, &dev_attr_wlc_fan_speed);
device_create_file(dev, &dev_attr_wlc_light_ctl);
device_create_file(dev, &dev_attr_wlc_tx_power);
device_create_file(dev, &dev_attr_wlc_tx_type);
device_create_file(dev, &dev_attr_wlc_st_changed);
device_create_file(dev, &dev_attr_ppp_cmd);
}
@ -1733,7 +1946,6 @@ err_irq_gpio:
return ret;
}
static void cps_wls_lock_work_init(struct cps_wls_chrg_chip *chip)
{
mutex_init(&chip->irq_lock);
@ -1855,6 +2067,11 @@ static int cps_wls_chrg_probe(struct i2c_client *client,
chip->client = client;
chip->dev = &client->dev;
chip->name = "cps_wls";
chip->is_charger_full = false;
chip->op_mode = MMI_WLC_NONE;
chip->fan_speed = 1;
chip->light_level = 1;
chip->regmap = devm_regmap_init_i2c(client, &cps4019_regmap_config);
if (IS_ERR(chip->regmap)) {
cps_wls_log(CPS_LOG_ERR, "[%s] Failed to allocate regmap!\n", __func__);
@ -1900,6 +2117,8 @@ static int cps_wls_chrg_probe(struct i2c_client *client,
}
}
chip->is_factory_mode = mmi_is_factory_mode();
cps_wls_create_device_node(&(client->dev));
chip->otg_channel = devm_iio_channel_get(chip->dev, "otg_enable");

View file

@ -25,8 +25,8 @@
#define INT_OC (0x01 << 4)
#define INT_ID_CFG_FINISH (0x01 << 5)
#define INT_VOUT_STATE (0x01 << 6)
#define INT_RSV_BIT_7 (0x01 << 7)
#define INT_RSV_BIT_8 (0x01 << 8)
#define INT_HS_OK (0x01 << 7)
#define INT_HS_FAIL (0x01 << 8)
#define INT_RSV_BIT_9 (0x01 << 9)
#define INT_RSV_BIT_A (0x01 << 10)
#define INT_RSV_BIT_B (0x01 << 11)