From 6f1bbe9f80bfaeee0cceb718a05b67570b60a856 Mon Sep 17 00:00:00 2001 From: yanyh2 Date: Sun, 26 Sep 2021 20:54:06 +0800 Subject: [PATCH] Add OEM glink notification and notifier call chain Add OEM glink notification for qti glink charger and add qti charger notifier call chain to extend the qti glink charger to be as communication proxy between AP and ADSP battery manager. Change-Id: I4351e2842e5f2105461a0d1d4bd2e5c8cdcd5d3e Signed-off-by: yanyh2 Reviewed-on: https://gerrit.mot.com/2076935 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Wentao Xu Reviewed-by: Jianqi Yang Submit-Approved: Jira Key --- .../qti_glink_charger/qti_glink_charger.c | 141 +++++++++++++----- .../qti_glink_charger/qti_glink_charger.h | 69 +++++++++ 2 files changed, 176 insertions(+), 34 deletions(-) create mode 100644 drivers/power/qti_glink_charger/qti_glink_charger.h diff --git a/drivers/power/qti_glink_charger/qti_glink_charger.c b/drivers/power/qti_glink_charger/qti_glink_charger.c index 3dd8fd2a7a22..af6e2e585966 100644 --- a/drivers/power/qti_glink_charger/qti_glink_charger.c +++ b/drivers/power/qti_glink_charger/qti_glink_charger.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Motorola Mobility LLC + * Copyright (C) 2020-2021 Motorola Mobility LLC * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -29,14 +29,17 @@ #include #include "mmi_charger.h" +#include "qti_glink_charger.h" /* PPM specific definitions */ #define MSG_OWNER_OEM 32782 #define MSG_TYPE_REQ_RESP 1 +#define MSG_TYPE_NOTIFY 2 #define OEM_PROPERTY_DATA_SIZE 16 #define OEM_READ_BUF_REQ 0x10000 #define OEM_WRITE_BUF_REQ 0x10001 +#define OEM_NOTIFY_IND 0x10002 #define OEM_WAIT_TIME_MS 5000 @@ -51,37 +54,6 @@ static bool debug_enabled; module_param(debug_enabled, bool, 0600); MODULE_PARM_DESC(debug_enabled, "Enable debug for qti glink charger driver"); -enum oem_property_type { - OEM_PROP_BATT_INFO, - OEM_PROP_CHG_INFO, - OEM_PROP_CHG_PROFILE_INFO, - OEM_PROP_CHG_PROFILE_DATA, - OEM_PROP_CHG_FV, - OEM_PROP_CHG_FCC, - OEM_PROP_CHG_ITERM, - OEM_PROP_CHG_FG_ITERM, - OEM_PROP_CHG_BC_PMAX, - OEM_PROP_CHG_QC_PMAX, - OEM_PROP_CHG_PD_PMAX, - OEM_PROP_CHG_WLS_PMAX, - OEM_PROP_CHG_SUSPEND, - OEM_PROP_CHG_DISABLE, - OEM_PROP_DEMO_MODE, - OEM_PROP_FACTORY_MODE, - OEM_PROP_FACTORY_VERSION, - OEM_PROP_TCMD, - OEM_PROP_PMIC_ICL, - OEM_PROP_REG_ADDRESS, - OEM_PROP_REG_DATA, - OEM_PROP_LPD_INFO, - OEM_PROP_USB_SUSPEND, - OEM_PROP_WLS_EN, - OEM_PROP_WLS_VOLT_MAX, - OEM_PROP_WLS_CURR_MAX, - OEM_PROP_WLS_CHIP_ID, - OEM_PROP_MAX, -}; - struct battery_info { int batt_uv; int batt_ua; @@ -118,6 +90,13 @@ struct lpd_info { int lpd_rsbu2; }; +struct oem_notify_ind_msg { + struct pmic_glink_hdr hdr; + u32 notification; + u32 receiver; + u32 data[MAX_OEM_NOTIFY_DATA_LEN]; +}; + struct oem_read_buf_req_msg { struct pmic_glink_hdr hdr; u32 oem_property_id; @@ -154,6 +133,8 @@ struct qti_charger { struct oem_read_buf_resp_msg rx_buf; atomic_t rx_valid; struct work_struct setup_work; + struct work_struct notify_work; + struct oem_notify_ind_msg notify_msg; atomic_t state; u32 chrg_taper_cnt; struct mmi_battery_info batt_info; @@ -168,6 +149,9 @@ struct qti_charger { bool *debug_enabled; }; +static struct qti_charger *this_chip = NULL; +static BLOCKING_NOTIFIER_HEAD(qti_chg_notifier_list); + static int find_profile_id(struct qti_charger *chg) { int i; @@ -271,6 +255,26 @@ static int handle_oem_write_ack(struct qti_charger *chg, void *data, size_t len) return 0; } +static int handle_oem_notification(struct qti_charger *chg, void *data, size_t len) +{ + struct oem_notify_ind_msg *notify_msg = data; + if (len != sizeof(*notify_msg)) { + mmi_err(chg, "Incorrect received length %zu expected %lu\n", len, + sizeof(*notify_msg)); + return -EINVAL; + } + + mmi_info(chg, "notification: %#x on receiver: %#x\n", + notify_msg->notification, + notify_msg->receiver); + + pm_stay_awake(chg->dev); + memcpy(&chg->notify_msg, notify_msg, sizeof(*notify_msg)); + schedule_work(&chg->notify_work); + + return 0; +} + static int oem_callback(void *priv, void *data, size_t len) { struct pmic_glink_hdr *hdr = data; @@ -283,6 +287,8 @@ static int oem_callback(void *priv, void *data, size_t len) handle_oem_read_ack(chg, data, len); else if (hdr->opcode == OEM_WRITE_BUF_REQ) handle_oem_write_ack(chg, data, len); + else if (hdr->opcode == OEM_NOTIFY_IND) + handle_oem_notification(chg, data, len); else mmi_err(chg, "Unknown message opcode: %d\n", hdr->opcode); @@ -409,6 +415,13 @@ static int qti_charger_read(struct qti_charger *chg, u32 property, goto out; } + if (chg->rx_buf.data_size != val_len) { + mmi_err(chg, "Invalid data size %u, on property: %u\n", + chg->rx_buf.data_size, property); + rc = -ENODATA; + goto out; + } + memcpy(val, chg->rx_buf.buf, val_len); atomic_set(&chg->rx_valid, 0); out: @@ -418,6 +431,44 @@ out: return rc; } +int qti_charger_set_property(u32 property, const void *val, size_t val_len) +{ + struct qti_charger *chg = this_chip; + + if (!chg) { + pr_err("QTI: chip not valid\n"); + return -ENODEV; + } + + return qti_charger_write(chg, property, val, val_len); +} +EXPORT_SYMBOL(qti_charger_set_property); + +int qti_charger_get_property(u32 property, void *val, size_t val_len) +{ + struct qti_charger *chg = this_chip; + + if (!chg) { + pr_err("QTI: chip not valid\n"); + return -ENODEV; + } + + return qti_charger_read(chg, property, val, val_len); +} +EXPORT_SYMBOL(qti_charger_get_property); + +int qti_charger_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register(&qti_chg_notifier_list, nb); +} +EXPORT_SYMBOL(qti_charger_register_notifier); + +int qti_charger_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister(&qti_chg_notifier_list, nb); +} +EXPORT_SYMBOL(qti_charger_unregister_notifier); + static int qti_charger_get_batt_info(void *data, struct mmi_battery_info *batt_info) { int rc; @@ -463,8 +514,10 @@ static int qti_charger_get_chg_info(void *data, struct mmi_charger_info *chg_inf rc = qti_charger_read(chg, OEM_PROP_LPD_INFO, &chg->lpd_info, sizeof(struct lpd_info)); - if (rc) - return rc; + if (rc) { + rc = 0; + memset(&chg->lpd_info, 0, sizeof(struct lpd_info)); + } mmi_info(chg, "LPD: present=%d, rsbu1=%d, rsbu2=%d\n", chg->lpd_info.lpd_present, chg->lpd_info.lpd_rsbu1, @@ -1283,6 +1336,23 @@ static void qti_charger_setup_work(struct work_struct *work) } } +static void qti_charger_notify_work(struct work_struct *work) +{ + unsigned long notification; + struct qti_charger_notify_data notify_data; + struct qti_charger *chg = container_of(work, + struct qti_charger, notify_work); + + notification = chg->notify_msg.notification; + notify_data.receiver = chg->notify_msg.receiver; + memcpy(notify_data.data, chg->notify_msg.data, + sizeof(u32) * MAX_OEM_NOTIFY_DATA_LEN); + blocking_notifier_call_chain(&qti_chg_notifier_list, + notification, + ¬ify_data); + pm_relax(chg->dev); +} + static int qti_charger_parse_dt(struct qti_charger *chg) { int rc; @@ -1418,6 +1488,7 @@ static int qti_charger_probe(struct platform_device *pdev) return -ENOMEM; INIT_WORK(&chg->setup_work, qti_charger_setup_work); + INIT_WORK(&chg->notify_work, qti_charger_notify_work); mutex_init(&chg->read_lock); mutex_init(&chg->write_lock); init_completion(&chg->read_ack); @@ -1454,6 +1525,8 @@ static int qti_charger_probe(struct platform_device *pdev) return rc; } + this_chip = chg; + device_init_wakeup(chg->dev, true); qti_charger_init(chg); return 0; diff --git a/drivers/power/qti_glink_charger/qti_glink_charger.h b/drivers/power/qti_glink_charger/qti_glink_charger.h new file mode 100644 index 000000000000..27946bb29752 --- /dev/null +++ b/drivers/power/qti_glink_charger/qti_glink_charger.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 Motorola Mobility LLC + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __QTI_GLINK_CHARGER_H__ +#define __QTI_GLINK_CHARGER_H__ + +/*OEM receivers maps*/ +#define OEM_NOTIFY_RECEIVER_PEN_CHG 0x0 +#define OEM_NOTIFY_RECEIVER_EXT_CHG 0x1 + +#define MAX_OEM_NOTIFY_DATA_LEN 8 + +enum oem_property_type { + OEM_PROP_BATT_INFO, + OEM_PROP_CHG_INFO, + OEM_PROP_CHG_PROFILE_INFO, + OEM_PROP_CHG_PROFILE_DATA, + OEM_PROP_CHG_FV, + OEM_PROP_CHG_FCC, + OEM_PROP_CHG_ITERM, + OEM_PROP_CHG_FG_ITERM, + OEM_PROP_CHG_BC_PMAX, + OEM_PROP_CHG_QC_PMAX, + OEM_PROP_CHG_PD_PMAX, + OEM_PROP_CHG_WLS_PMAX, + OEM_PROP_CHG_SUSPEND, + OEM_PROP_CHG_DISABLE, + OEM_PROP_DEMO_MODE, + OEM_PROP_FACTORY_MODE, + OEM_PROP_FACTORY_VERSION, + OEM_PROP_TCMD, + OEM_PROP_PMIC_ICL, + OEM_PROP_REG_ADDRESS, + OEM_PROP_REG_DATA, + OEM_PROP_LPD_INFO, + OEM_PROP_USB_SUSPEND, + OEM_PROP_WLS_EN, + OEM_PROP_WLS_VOLT_MAX, + OEM_PROP_WLS_CURR_MAX, + OEM_PROP_WLS_CHIP_ID, + OEM_PROP_PEN_CTRL, + OEM_PROP_PEN_ID, + OEM_PROP_PEN_SOC, + OEM_PROP_PEN_MAC, + OEM_PROP_PEN_STATUS, + OEM_PROP_MAX, +}; + +struct qti_charger_notify_data { + u32 receiver; + u32 data[MAX_OEM_NOTIFY_DATA_LEN]; +}; + +extern int qti_charger_set_property(u32 property, const void *val, size_t val_len); +extern int qti_charger_get_property(u32 property, void *val, size_t val_len); +extern int qti_charger_register_notifier(struct notifier_block *nb); +extern int qti_charger_unregister_notifier(struct notifier_block *nb); + +#endif