diff options
| -rw-r--r-- | arch/arm64/configs/msm-perf_defconfig | 1 | ||||
| -rw-r--r-- | arch/arm64/configs/msm_defconfig | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/bus.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/bus.h | 3 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/main.c | 86 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/main.h | 9 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/qmi.c | 290 | ||||
| -rw-r--r-- | drivers/net/wireless/cnss2/qmi.h | 7 | ||||
| -rw-r--r-- | drivers/power/power_supply_sysfs.c | 4 | ||||
| -rw-r--r-- | drivers/power/supply/qcom/qpnp-fg.c | 76 | ||||
| -rw-r--r-- | include/linux/power_supply.h | 4 |
11 files changed, 413 insertions, 80 deletions
diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index a2c361e9fe7c..a6e5ec7bda6a 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -257,6 +257,7 @@ CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig index ac99f2ac57b2..14ed727da342 100644 --- a/arch/arm64/configs/msm_defconfig +++ b/arch/arm64/configs/msm_defconfig @@ -249,6 +249,7 @@ CONFIG_DM_CRYPT=y CONFIG_DM_REQ_CRYPT=y CONFIG_DM_UEVENT=y CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y CONFIG_BONDING=y CONFIG_DUMMY=y diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c index d8d8d5b75853..0411f7eb4ea1 100644 --- a/drivers/net/wireless/cnss2/bus.c +++ b/drivers/net/wireless/cnss2/bus.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -56,16 +56,6 @@ bool cnss_bus_req_mem_ind_valid(struct cnss_plat_data *plat_priv) return true; } -bool cnss_bus_dev_cal_rep_valid(struct cnss_plat_data *plat_priv) -{ - bool ret = false; - - if (cnss_get_bus_type(plat_priv->device_id) == CNSS_BUS_USB) - ret = true; - - return ret; -} - void *cnss_bus_dev_to_bus_priv(struct device *dev) { if (!dev) diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h index ff5f5a85469e..f9168c3ade93 100644 --- a/drivers/net/wireless/cnss2/bus.h +++ b/drivers/net/wireless/cnss2/bus.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -58,5 +58,4 @@ int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv, int modem_current_status); int cnss_bus_recovery_update_status(struct cnss_plat_data *plat_priv); bool cnss_bus_req_mem_ind_valid(struct cnss_plat_data *plat_priv); -bool cnss_bus_dev_cal_rep_valid(struct cnss_plat_data *plat_priv); #endif /* _CNSS_BUS_H */ diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 249e3da75c98..df5f72c7b25d 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -562,13 +562,49 @@ out: return ret; } -static int cnss_cal_update_hdlr(struct cnss_plat_data *plat_priv) +static int caldb_mem_bounds_check(struct cnss_plat_data *plat_priv, void *data) { - /* QCN7605 store the cal data sent by FW to calDB memory area - * get out of this after complete data is uploaded. FW is expected - * to send cal done - */ - return 0; + int ret = 0; + struct cnss_cal_data *cal_data = data; + u8 *end_ptr, *cal_data_ptr; + u32 total_size; + + end_ptr = (u8 *)plat_priv->caldb_mem + QCN7605_CALDB_SIZE; + cal_data_ptr = (u8 *)plat_priv->caldb_mem + cal_data->index; + total_size = cal_data->total_size; + + if (cal_data_ptr >= end_ptr || (cal_data_ptr + total_size) >= end_ptr) { + cnss_pr_err("caldb data offset or size error\n"); + ret = -EINVAL; + } + + return ret; +} + +static int cnss_cal_update_hdlr(struct cnss_plat_data *plat_priv, void *data) +{ + int ret = 0; + + ret = caldb_mem_bounds_check(plat_priv, data); + if (ret) + CNSS_ASSERT(0); + else + cnss_wlfw_cal_update_req_send_sync(plat_priv, data); + + return ret; +} + +static int cnss_cal_download_hdlr(struct cnss_plat_data *plat_priv, void *data) +{ + int ret = 0; + + ret = caldb_mem_bounds_check(plat_priv, data); + if (ret) + CNSS_ASSERT(0); + else + cnss_wlfw_cal_download_req_send_sync(plat_priv, data); + + return ret; } static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) @@ -1157,11 +1193,6 @@ static int cnss_wlfw_server_arrive_hdlr(struct cnss_plat_data *plat_priv) goto out; ret = cnss_wlfw_bdf_dnld_send_sync(plat_priv); - if (ret) - goto out; - /*cnss driver sends meta data report and waits for FW_READY*/ - if (cnss_bus_dev_cal_rep_valid(plat_priv)) - ret = cnss_wlfw_cal_report_send_sync(plat_priv); } out: return ret; @@ -1255,7 +1286,10 @@ static void cnss_driver_event_work(struct work_struct *work) ret = cnss_cold_boot_cal_start_hdlr(plat_priv); break; case CNSS_DRIVER_EVENT_CAL_UPDATE: - ret = cnss_cal_update_hdlr(plat_priv); + ret = cnss_cal_update_hdlr(plat_priv, event->data); + break; + case CNSS_DRIVER_EVENT_CAL_DOWNLOAD: + ret = cnss_cal_download_hdlr(plat_priv, event->data); break; case CNSS_DRIVER_EVENT_COLD_BOOT_CAL_DONE: ret = cnss_cold_boot_cal_done_hdlr(plat_priv); @@ -1696,6 +1730,25 @@ static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv) destroy_workqueue(plat_priv->event_wq); } +static int cnss_alloc_caldb_mem(struct cnss_plat_data *plat_priv) +{ + int ret = 0; + + plat_priv->caldb_mem = vzalloc(QCN7605_CALDB_SIZE); + if (plat_priv->caldb_mem) + cnss_pr_dbg("600KB cal db alloc done caldb_mem %pK\n", + plat_priv->caldb_mem); + else + ret = -ENOMEM; + + return ret; +} + +static void cnss_free_caldb_mem(struct cnss_plat_data *plat_priv) +{ + vfree(plat_priv->caldb_mem); +} + static const struct platform_device_id cnss_platform_id_table[] = { { .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, }, { .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, }, @@ -1786,6 +1839,12 @@ static int cnss_probe(struct platform_device *plat_dev) if (ret) goto deinit_qmi; + if (plat_priv->bus_type == CNSS_BUS_USB) { + ret = cnss_alloc_caldb_mem(plat_priv); + if (ret) + goto remove_debugfs; + } + setup_timer(&plat_priv->fw_boot_timer, cnss_bus_fw_boot_timeout_hdlr, (unsigned long)plat_priv); @@ -1803,6 +1862,8 @@ static int cnss_probe(struct platform_device *plat_dev) return 0; +remove_debugfs: + cnss_debugfs_destroy(plat_priv); deinit_qmi: cnss_qmi_deinit(plat_priv); deinit_event_work: @@ -1836,6 +1897,7 @@ static int cnss_remove(struct platform_device *plat_dev) device_init_wakeup(&plat_dev->dev, false); unregister_pm_notifier(&cnss_pm_notifier); del_timer(&plat_priv->fw_boot_timer); + cnss_free_caldb_mem(plat_priv); cnss_debugfs_destroy(plat_priv); cnss_qmi_deinit(plat_priv); cnss_event_work_deinit(plat_priv); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index ec67d31ea945..28469dfc96af 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -29,6 +29,7 @@ #define CNSS_EVENT_UNINTERRUPTIBLE BIT(1) #define CNSS_EVENT_SYNC_UNINTERRUPTIBLE (CNSS_EVENT_SYNC | \ CNSS_EVENT_UNINTERRUPTIBLE) +#define QCN7605_CALDB_SIZE 614400 enum cnss_dev_bus_type { CNSS_BUS_NONE = -1, @@ -174,6 +175,11 @@ enum cnss_debug_quirks { SKIP_RECOVERY, }; +struct cnss_cal_data { + u32 index; + u32 total_size; +}; + struct cnss_plat_data { struct platform_device *plat_dev; void *bus_priv; @@ -216,6 +222,7 @@ struct cnss_plat_data { u32 diag_reg_read_mem_type; u32 diag_reg_read_len; u8 *diag_reg_read_buf; + void *caldb_mem; bool cal_done; }; diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index cd84f74a3d46..3fbfb590a384 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -175,11 +175,13 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) req.bdf_support_valid = 1; req.bdf_support = 1; - req.m3_support_valid = 1; - req.m3_support = 1; + if (cnss_get_bus_type(plat_priv->device_id) == CNSS_BUS_PCI) { + req.m3_support_valid = 1; + req.m3_support = 1; - req.m3_cache_support_valid = 1; - req.m3_cache_support = 1; + req.m3_cache_support_valid = 1; + req.m3_cache_support = 1; + } req.cal_done_valid = 1; req.cal_done = plat_priv->cal_done; @@ -279,7 +281,83 @@ static int cnss_qmi_initiate_cal_update_ind_hdlr( struct cnss_plat_data *plat_priv, void *msg, unsigned int msg_len) { - return 0; + struct msg_desc ind_desc; + struct wlfw_initiate_cal_update_ind_msg_v01 ind_msg; + struct cnss_cal_data *data; + int ret = 0; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto out; + } + + ind_desc.msg_id = QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01; + ind_desc.max_msg_len = WLFW_INITIATE_CAL_UPDATE_IND_MSG_V01_MAX_MSG_LEN; + ind_desc.ei_array = wlfw_initiate_cal_update_ind_msg_v01_ei; + + ret = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len); + if (ret < 0) { + cnss_pr_err("Failed to decode initiate cal update ind, msg_len: %u, err = %d\n", + ret, msg_len); + goto qmi_fail; + } + + if ((ind_msg.total_size > 0) && (ind_msg.cal_data_location_valid)) { + data->index = ind_msg.cal_data_location; + data->total_size = ind_msg.total_size; + cnss_driver_event_post(plat_priv, CNSS_DRIVER_EVENT_CAL_UPDATE, + 0, data); + goto out; + } + +qmi_fail: + kfree(data); +out: + return ret; +} + +static int cnss_qmi_initiate_cal_download_ind_hdlr( + struct cnss_plat_data *plat_priv, + void *msg, unsigned int msg_len) +{ + struct msg_desc ind_desc; + struct wlfw_initiate_cal_download_ind_msg_v01 ind_msg; + struct cnss_cal_data *data; + int ret = 0; + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto out; + } + + ind_desc.msg_id = QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01; + ind_desc.max_msg_len = + WLFW_INITIATE_CAL_DOWNLOAD_IND_MSG_V01_MAX_MSG_LEN; + ind_desc.ei_array = wlfw_initiate_cal_download_ind_msg_v01_ei; + + ret = qmi_kernel_decode(&ind_desc, &ind_msg, msg, msg_len); + if (ret < 0) { + cnss_pr_err("Failed to decode initiate cal download ind, msg_len: %u, err = %d\n", + ret, msg_len); + goto qmi_fail; + } + + if ((ind_msg.total_size > 0) && (ind_msg.cal_data_location_valid)) { + data->index = ind_msg.cal_data_location; + data->total_size = ind_msg.total_size; + cnss_driver_event_post(plat_priv, + CNSS_DRIVER_EVENT_CAL_DOWNLOAD, + 0, data); + + goto out; + } + +qmi_fail: + kfree(data); +out: + return ret; } static int cnss_wlfw_request_mem_ind_hdlr(struct cnss_plat_data *plat_priv, @@ -501,6 +579,197 @@ out: return ret; } +int cnss_wlfw_cal_download_req_send_sync(struct cnss_plat_data *plat_priv, + void *data) +{ + struct wlfw_cal_download_req_msg_v01 *req; + struct wlfw_cal_download_resp_msg_v01 resp; + struct cnss_cal_data *cal_data = data; + struct msg_desc req_desc, resp_desc; + unsigned int remaining; + u8 *cal_data_read_ptr; + int ret = 0; + + cnss_pr_dbg("Sending cal download request message, state: 0x%lx\n", + plat_priv->driver_state); + + req = kzalloc(sizeof(*req), GFP_KERNEL); + if (!req) { + ret = -ENOMEM; + goto out; + } + + memset(&resp, 0, sizeof(resp)); + + req_desc.max_msg_len = WLFW_CAL_DOWNLOAD_REQ_MSG_V01_MAX_MSG_LEN; + req_desc.msg_id = QMI_WLFW_CAL_DOWNLOAD_REQ_V01; + req_desc.ei_array = wlfw_cal_download_req_msg_v01_ei; + + resp_desc.max_msg_len = WLFW_CAL_DOWNLOAD_RESP_MSG_V01_MAX_MSG_LEN; + resp_desc.msg_id = QMI_WLFW_CAL_DOWNLOAD_RESP_V01; + resp_desc.ei_array = wlfw_cal_download_resp_msg_v01_ei; + + req->valid = true; + req->file_id_valid = false; + req->seg_id_valid = true; + req->seg_id = 0; + req->data_valid = true; + req->end_valid = true; + req->total_size_valid = true; + req->total_size = cal_data->total_size; + + req->cal_data_location_valid = true; + req->cal_data_location = cal_data->index; + cal_data_read_ptr = (u8 *)plat_priv->caldb_mem + + cal_data->index; + cnss_pr_dbg("cal_data_read_ptr %pK\n", cal_data_read_ptr); + remaining = cal_data->total_size; + + while (remaining) { + if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { + req->data_len = QMI_WLFW_MAX_DATA_SIZE_V01; + } else { + req->data_len = remaining; + req->end = true; + } + + memcpy(req->data, cal_data_read_ptr, req->data_len); + cnss_pr_dbg("remaining %u data_len %u, seg_id %u, read_ptr %pK\n", + remaining, req->data_len, req->seg_id, + cal_data_read_ptr); + + ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, + req, sizeof(*req), &resp_desc, &resp, + sizeof(resp), QMI_WLFW_TIMEOUT_MS); + if (ret < 0) { + cnss_pr_err("Failed to send cal download request, err = %d\n", + ret); + goto out; + } + + if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { + cnss_pr_err("cal download request failed, result: %d, err: %d\n", + resp.resp.result, resp.resp.error); + ret = resp.resp.result; + goto out; + } + + remaining -= req->data_len; + cal_data_read_ptr += req->data_len; + req->seg_id++; + } + +out: + kfree(req); + kfree(data); + if (ret) + CNSS_ASSERT(0); + return ret; +} + +int cnss_wlfw_cal_update_req_send_sync(struct cnss_plat_data *plat_priv, + void *data) +{ + struct wlfw_cal_update_req_msg_v01 req; + struct wlfw_cal_update_resp_msg_v01 *resp = NULL; + struct cnss_cal_data *cal_data = data; + struct msg_desc req_desc, resp_desc; + unsigned int remaining, data_len; + u8 *cal_data_write_ptr; + bool end = false; + int ret = 0; + + cnss_pr_dbg("Sending cal update request message, state: 0x%lx\n", + plat_priv->driver_state); + + resp = kzalloc(sizeof(*resp), GFP_KERNEL); + if (!resp) { + ret = -ENOMEM; + goto out; + } + + memset(resp, 0, sizeof(*resp)); + + req_desc.max_msg_len = WLFW_CAL_UPDATE_REQ_MSG_V01_MAX_MSG_LEN; + req_desc.msg_id = QMI_WLFW_CAL_UPDATE_REQ_V01; + req_desc.ei_array = wlfw_cal_update_req_msg_v01_ei; + + resp_desc.max_msg_len = WLFW_CAL_UPDATE_RESP_MSG_V01_MAX_MSG_LEN; + resp_desc.msg_id = QMI_WLFW_CAL_UPDATE_RESP_V01; + resp_desc.ei_array = wlfw_cal_update_resp_msg_v01_ei; + + req.cal_id = 0; + req.seg_id = 0; + cal_data_write_ptr = (u8 *)plat_priv->caldb_mem + + cal_data->index; + remaining = cal_data->total_size; + + while (remaining) { + if (remaining > QMI_WLFW_MAX_DATA_SIZE_V01) { + data_len = QMI_WLFW_MAX_DATA_SIZE_V01; + } else { + data_len = remaining; + end = true; + } + + cnss_pr_dbg("remaining %u data_len %u, seg_id %u\n", + remaining, data_len, req.seg_id); + + ret = qmi_send_req_wait(plat_priv->qmi_wlfw_clnt, &req_desc, + &req, sizeof(req), &resp_desc, resp, + sizeof(*resp), QMI_WLFW_TIMEOUT_MS); + if (ret < 0) { + cnss_pr_err("Failed to send cal update request, err = %d\n", + ret); + goto out; + } + + if (resp->resp.result != QMI_RESULT_SUCCESS_V01) { + cnss_pr_err("cal update request failed, result: %d, err: %d\n", + resp->resp.result, resp->resp.error); + ret = resp->resp.result; + goto out; + } + + if (!resp->data_valid || resp->data_len != data_len) { + cnss_pr_err("cal update read data is invalid, data_valid = %u, data_len = %u\n", + resp->data_valid, resp->data_len); + ret = -EINVAL; + goto out; + } + + if (!resp->seg_id_valid || resp->seg_id != req.seg_id) { + cnss_pr_err("seg_id invalid, valid = %u, seg_id = %u, req seg id =%u\n", + resp->seg_id_valid, resp->seg_id, + req.seg_id); + ret = -EINVAL; + goto out; + } + + if (resp->end_valid && resp->end) { + cnss_pr_dbg("cal update end valid =%u end = %u\n", + resp->end_valid, resp->end); + /*one valid cal data is available with host*/ + plat_priv->cal_done = true; + } + + memcpy(cal_data_write_ptr, resp->data, resp->data_len); + cnss_pr_dbg("cal updated resp->data_len %u\n", resp->data_len); + remaining -= resp->data_len; + cal_data_write_ptr += resp->data_len; + req.seg_id++; + + memset(resp, 0, sizeof(*resp)); + } + +out: + kfree(resp); + kfree(data); + if (ret) + CNSS_ASSERT(0); + return ret; +} + int cnss_wlfw_bdf_dnld_send_sync(struct cnss_plat_data *plat_priv) { struct wlfw_bdf_download_req_msg_v01 *req; @@ -965,11 +1234,6 @@ out: return ret; } -int cnss_wlfw_cal_report_send_sync(struct cnss_plat_data *plat_priv) -{ - return 0; -} - static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, unsigned int msg_id, void *msg, unsigned int msg_len, void *ind_cb_priv) @@ -1009,6 +1273,10 @@ static void cnss_wlfw_clnt_ind(struct qmi_handle *handle, case QMI_WLFW_INITIATE_CAL_UPDATE_IND_V01: cnss_qmi_initiate_cal_update_ind_hdlr(plat_priv, msg, msg_len); break; + case QMI_WLFW_INITIATE_CAL_DOWNLOAD_IND_V01: + cnss_qmi_initiate_cal_download_ind_hdlr(plat_priv, + msg, msg_len); + break; default: cnss_pr_err("Invalid QMI WLFW indication, msg_id: 0x%x\n", msg_id); diff --git a/drivers/net/wireless/cnss2/qmi.h b/drivers/net/wireless/cnss2/qmi.h index c6a1e6733505..f11e19ead482 100644 --- a/drivers/net/wireless/cnss2/qmi.h +++ b/drivers/net/wireless/cnss2/qmi.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -37,5 +37,8 @@ int cnss_wlfw_athdiag_write_send_sync(struct cnss_plat_data *plat_priv, u32 data_len, u8 *data); int cnss_wlfw_ini_send_sync(struct cnss_plat_data *plat_priv, u8 fw_log_mode); -int cnss_wlfw_cal_report_send_sync(struct cnss_plat_data *plat_priv); +int cnss_wlfw_cal_update_req_send_sync(struct cnss_plat_data *plat_priv, + void *data); +int cnss_wlfw_cal_download_req_send_sync(struct cnss_plat_data *plat_priv, + void *data); #endif /* _CNSS_QMI_H */ diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c index 1974d6ee032b..58ec25cab969 100644 --- a/drivers/power/power_supply_sysfs.c +++ b/drivers/power/power_supply_sysfs.c @@ -306,6 +306,10 @@ static struct device_attribute power_supply_attrs[] = { POWER_SUPPLY_ATTR(pd_voltage_min), POWER_SUPPLY_ATTR(sdp_current_max), POWER_SUPPLY_ATTR(fcc_stepper_enable), + POWER_SUPPLY_ATTR(ignore_false_negative_isense), + POWER_SUPPLY_ATTR(battery_info), + POWER_SUPPLY_ATTR(battery_info_id), + POWER_SUPPLY_ATTR(enable_jeita_detection), /* Local extensions of type int64_t */ POWER_SUPPLY_ATTR(charge_counter_ext), /* Properties of type `const char *' */ diff --git a/drivers/power/supply/qcom/qpnp-fg.c b/drivers/power/supply/qcom/qpnp-fg.c index cfd2f64a9bb8..a12b0adfa32d 100644 --- a/drivers/power/supply/qcom/qpnp-fg.c +++ b/drivers/power/supply/qcom/qpnp-fg.c @@ -277,7 +277,7 @@ static struct fg_mem_data fg_data[FG_DATA_MAX] = { static int fg_debug_mask; module_param_named( - debug_mask, fg_debug_mask, int, S_IRUSR | S_IWUSR + debug_mask, fg_debug_mask, int, 00600 ); static int fg_sense_type = -EINVAL; @@ -285,17 +285,17 @@ static int fg_restart; static int fg_est_dump; module_param_named( - first_est_dump, fg_est_dump, int, S_IRUSR | S_IWUSR + first_est_dump, fg_est_dump, int, 00600 ); static char *fg_batt_type; module_param_named( - battery_type, fg_batt_type, charp, S_IRUSR | S_IWUSR + battery_type, fg_batt_type, charp, 00600 ); static int fg_sram_update_period_ms = 30000; module_param_named( - sram_update_period_ms, fg_sram_update_period_ms, int, S_IRUSR | S_IWUSR + sram_update_period_ms, fg_sram_update_period_ms, int, 00600 ); struct fg_irq { @@ -528,7 +528,7 @@ struct fg_chip { #define MAX_REG_PER_TRANSACTION (8) static const char *DFS_ROOT_NAME = "fg_memif"; -static const mode_t DFS_MODE = S_IRUSR | S_IWUSR; +static const mode_t DFS_MODE = 00600; static const char *default_batt_type = "Unknown Battery"; static const char *loading_batt_type = "Loading Battery Data"; static const char *missing_batt_type = "Disconnected Battery"; @@ -810,9 +810,8 @@ static int fg_release_access(struct fg_chip *chip) static void fg_release_access_if_necessary(struct fg_chip *chip) { mutex_lock(&chip->rw_lock); - if (atomic_sub_return(1, &chip->memif_user_cnt) <= 0) { + if (atomic_sub_return(1, &chip->memif_user_cnt) <= 0) fg_release_access(chip); - } mutex_unlock(&chip->rw_lock); } @@ -879,7 +878,7 @@ static int fg_sub_mem_read(struct fg_chip *chip, u8 *val, u16 address, int len, MEM_INTF_RD_DATA0(chip) + offset, min(len, BUF_LEN - offset)); - /* manually set address to allow continous reads */ + /* manually set address to allow continuous reads */ address += BUF_LEN; rc = fg_set_ram_addr(chip, &address); @@ -1102,8 +1101,8 @@ static int fg_check_ima_exception(struct fg_chip *chip) IMA_IACS_CLR, 0, 1); if (!ret) return -EAGAIN; - else - pr_err("Error clearing IMA exception ret=%d\n", ret); + + pr_err("Error clearing IMA exception ret=%d\n", ret); } return rc; @@ -1123,14 +1122,13 @@ static int fg_check_iacs_ready(struct fg_chip *chip) while (1) { rc = fg_read(chip, &ima_opr_sts, chip->mem_base + MEM_INTF_IMA_OPR_STS, 1); - if (!rc && (ima_opr_sts & IMA_IACS_RDY)) { + if (!rc && (ima_opr_sts & IMA_IACS_RDY)) break; - } else { - if (!(--timeout) || rc) - break; - /* delay for iacs_ready to be asserted */ - usleep_range(5000, 7000); - } + + if (!(--timeout) || rc) + break; + /* delay for iacs_ready to be asserted */ + usleep_range(5000, 7000); } if (!timeout || rc) { @@ -1155,19 +1153,18 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u8 *val, len, address, offset); while (len > 0) { - num_bytes = (offset + len) > BUF_LEN ? - (BUF_LEN - offset) : len; - /* write to byte_enable */ - for (i = offset; i < (offset + num_bytes); i++) - byte_enable |= BIT(i); - - rc = fg_write(chip, &byte_enable, - chip->mem_base + MEM_INTF_IMA_BYTE_EN, 1); - if (rc) { - pr_err("Unable to write to byte_en_reg rc=%d\n", - rc); - return rc; - } + num_bytes = (offset + len) > BUF_LEN ? + (BUF_LEN - offset) : len; + /* write to byte_enable */ + for (i = offset; i < (offset + num_bytes); i++) + byte_enable |= BIT(i); + + rc = fg_write(chip, &byte_enable, + chip->mem_base + MEM_INTF_IMA_BYTE_EN, 1); + if (rc) { + pr_err("Unable to write to byte_en_reg rc=%d\n", rc); + return rc; + } /* write data */ rc = fg_write(chip, word, MEM_INTF_WR_DATA0(chip) + offset, num_bytes); @@ -1184,6 +1181,7 @@ static int __fg_interleaved_mem_write(struct fg_chip *chip, u8 *val, */ if (!(byte_enable & BIT(3))) { u8 dummy_byte = 0x0; + rc = fg_write(chip, &dummy_byte, MEM_INTF_WR_DATA0(chip) + 3, 1); if (rc) { @@ -1552,7 +1550,6 @@ static void batt_to_setpoint_adc(int vbatt_mv, u8 *data) val = DIV_ROUND_CLOSEST(vbatt_mv * 32768, 5000); data[0] = val & 0xFF; data[1] = val >> 8; - return; } static u8 batt_to_setpoint_8b(int vbatt_mv) @@ -3239,6 +3236,7 @@ fail: static bool is_usb_present(struct fg_chip *chip) { union power_supply_propval prop = {0,}; + if (!chip->usb_psy) chip->usb_psy = power_supply_get_by_name("usb"); @@ -3251,6 +3249,7 @@ static bool is_usb_present(struct fg_chip *chip) static bool is_dc_present(struct fg_chip *chip) { union power_supply_propval prop = {0,}; + if (!chip->dc_psy) chip->dc_psy = power_supply_get_by_name("dc"); @@ -3634,10 +3633,8 @@ static void dump_sram(struct work_struct *work) dump_sram); buffer = devm_kzalloc(chip->dev, SRAM_DUMP_LEN, GFP_KERNEL); - if (buffer == NULL) { - pr_err("Can't allocate buffer\n"); + if (buffer == NULL) return; - } rc = fg_read(chip, &rt_sts, INT_RT_STS(chip->soc_base), 1); if (rc) @@ -5697,10 +5694,8 @@ static int fg_memif_data_open(struct inode *inode, struct file *file) /* Per file "transaction" data */ trans = kzalloc(sizeof(*trans), GFP_KERNEL); - if (!trans) { - pr_err("Unable to allocate memory for transaction data\n"); + if (!trans) return -ENOMEM; - } /* Allocate log buffer */ log = kzalloc(logbufsize, GFP_KERNEL); @@ -6043,7 +6038,7 @@ static struct dentry *fg_dfs_create_fs(void) dbgfs_data.help_msg.size = strlen(dbgfs_data.help_msg.data); - file = debugfs_create_blob("help", S_IRUGO, root, &dbgfs_data.help_msg); + file = debugfs_create_blob("help", 0444, root, &dbgfs_data.help_msg); if (!file) { pr_err("error creating help entry\n"); goto err_remove_fs; @@ -6650,10 +6645,9 @@ static int fg_probe(struct platform_device *pdev) } chip = devm_kzalloc(dev, sizeof(struct fg_chip), GFP_KERNEL); - if (chip == NULL) { - pr_err("Can't allocate fg_chip\n"); + if (chip == NULL) return -ENOMEM; - } + chip->regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!chip->regmap) { dev_err(&pdev->dev, "Couldn't get parent's regmap\n"); diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index 6828063842df..23c1e473f34b 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -261,6 +261,10 @@ enum power_supply_property { POWER_SUPPLY_PROP_PD_VOLTAGE_MIN, POWER_SUPPLY_PROP_SDP_CURRENT_MAX, POWER_SUPPLY_PROP_FCC_STEPPER_ENABLE, + POWER_SUPPLY_PROP_IGNORE_FALSE_NEGATIVE_ISENSE, + POWER_SUPPLY_PROP_BATTERY_INFO, + POWER_SUPPLY_PROP_BATTERY_INFO_ID, + POWER_SUPPLY_PROP_ENABLE_JEITA_DETECTION, /* Local extensions of type int64_t */ POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT, /* Properties of type `const char *' */ |
