From 1680e1885fe59dc31944910b2594d10d24b5db99 Mon Sep 17 00:00:00 2001 From: Khageswararao Rao B Date: Wed, 31 Jan 2024 09:03:02 +0530 Subject: [PATCH] NFC: driver: Add SW WAR to enable and disable NFC clock Added SW WAR to enable NFC clock at NFC ON and disable NFC clock at NFC OFF. Change-Id: I74fd9fa58f9875e91807c4f06735b2c62867aaf7 Signed-off-by: Khageswararao Rao B --- BUILD.bazel | 2 ++ nfc/common.c | 61 +++++++++++++++++++++------------ nfc/common.h | 12 ++++++- nfc/common_qcom.c | 42 ++++++++++++++++++++++- nfc/i2c_drv.c | 11 +++--- nfc_kernel_dlkm_vendor_board.mk | 4 +-- 6 files changed, 103 insertions(+), 29 deletions(-) diff --git a/BUILD.bazel b/BUILD.bazel index dd3213e2a7..786eaababc 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -7,3 +7,5 @@ define_modules("pineapple", "gki") define_modules("blair", "consolidate") define_modules("blair", "gki") +define_modules("pitti", "consolidate") +define_modules("pitti", "gki") diff --git a/nfc/common.c b/nfc/common.c index a2306f7e82..64a57c3e2a 100644 --- a/nfc/common.c +++ b/nfc/common.c @@ -18,7 +18,7 @@ * ******************************************************************************/ /* - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * *****************************************************************************/ #include @@ -69,12 +69,16 @@ int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, pr_warn("NxpDrv: %s: dwl_req gpio invalid %d\n", __func__, nfc_gpio->dwl_req); } - /* Read clkreq GPIO pin number from DTSI */ - nfc_gpio->clkreq = of_get_named_gpio(np, DTS_CLKREQ_GPIO_STR, 0); - if (!gpio_is_valid(nfc_gpio->clkreq)) { - dev_err(dev, "NxpDrv: clkreq gpio invalid %d\n", nfc_gpio->clkreq); - return -EINVAL; - } + /* Read clock request gpio configuration if MGPIO configurations are not preasent */ + if (of_property_read_string(np, DTS_CLKSRC_GPIO_STR, &nfc_configs->clk_src_name)) { + nfc_configs->clk_pin_voting = false; + nfc_gpio->clkreq = of_get_named_gpio(np, DTS_CLKREQ_GPIO_STR, 0); + if (!gpio_is_valid(nfc_gpio->clkreq)) { + dev_err(dev, "NxpDrv: clkreq gpio invalid %d\n", nfc_gpio->clkreq); + return -EINVAL; + } + } else + nfc_configs->clk_pin_voting = true; #ifdef NFC_SECURE_PERIPHERAL_ENABLED /* Read DTS_SZONE_STR to check secure zone support */ @@ -403,9 +407,21 @@ static int nfc_ioctl_power_states(struct nfc_dev *nfc_dev, unsigned long arg) nfc_dev->nfc_state = NFC_STATE_NCI; } else if (arg == NFC_ENABLE) { + if (nfc_dev->configs.clk_pin_voting) { + /* Enabling nfc clock */ + ret = nfc_clock_select(nfc_dev); + if (ret) + pr_err("%s unable to select clock\n", __func__); + } /* Setting flag true when NFC is enabled */ nfc_dev->cold_reset.is_nfc_enabled = true; } else if (arg == NFC_DISABLE) { + if (nfc_dev->configs.clk_pin_voting) { + /* Disabling nfc clock */ + ret = nfc_clock_deselect(nfc_dev); + if (ret) + pr_err("%s unable to disable clock\n", __func__); + } /* Setting flag true when NFC is disabled */ nfc_dev->cold_reset.is_nfc_enabled = false; } else { @@ -478,20 +494,23 @@ int nfc_post_init(struct nfc_dev *nfc_dev) __func__, nfc_gpio->dwl_req); } - /* Read clkreq GPIO number from device tree*/ - ret = of_property_read_u32_index(nfc_dev->i2c_dev.client->dev.of_node, DTS_CLKREQ_GPIO_STR, 1, &clkreq_gpio); - if (ret < 0) { - pr_err("NxpDrv: %s Failed to read clkreq gipo number, ret: %d\n", __func__, ret); - return ret; - } - /* configure clkreq GPIO as wakeup capable */ - ret = msm_gpio_mpm_wake_set(clkreq_gpio, true); - if (ret < 0) { - pr_err("NxpDrv: %s Failed to setup clkreq gpio %d as wakeup capable, ret: %d\n", __func__, clkreq_gpio , ret); - return ret; - } else { - pr_info("NxpDrv: %s clkreq gpio %d successfully setup for wakeup capable\n", __func__, clkreq_gpio); - } + if (!(nfc_configs.clk_pin_voting)) { + /* Read clkreq GPIO number from device tree*/ + ret = of_property_read_u32_index(nfc_dev->i2c_dev.client->dev.of_node, + DTS_CLKREQ_GPIO_STR, 1, &clkreq_gpio); + if (ret < 0) { + pr_err("NxpDrv: %s Failed to read clkreq gipo number, ret: %d\n", + __func__, ret); + return ret; + } + /* configure clkreq GPIO as wakeup capable */ + ret = msm_gpio_mpm_wake_set(clkreq_gpio, true); + if (ret < 0) { + pr_err("NxpDrv: %s clkreq gpio %d as wakeup capable failed, ret: %d\n", + __func__, clkreq_gpio, ret); + return ret; + } + } ret = nfcc_hw_check(nfc_dev); if (ret || nfc_dev->nfc_state == NFC_STATE_UNKNOWN) { diff --git a/nfc/common.h b/nfc/common.h index d8362224f7..3c745eb9b7 100644 --- a/nfc/common.h +++ b/nfc/common.h @@ -18,7 +18,7 @@ * ******************************************************************************/ /* - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. *****************************************************************************/ #ifndef _COMMON_H_ #define _COMMON_H_ @@ -102,6 +102,7 @@ #define DTS_VEN_GPIO_STR "qcom,sn-ven" #define DTS_FWDN_GPIO_STR "qcom,sn-firm" #define DTS_CLKREQ_GPIO_STR "qcom,sn-clkreq" +#define DTS_CLKSRC_GPIO_STR "qcom,clk-src" #define DTS_SZONE_STR "qcom,sn-szone" #define NFC_LDO_SUPPLY_DT_NAME "qcom,sn-vdd-1p8" #define NFC_LDO_SUPPLY_NAME "qcom,sn-vdd-1p8-supply" @@ -237,6 +238,9 @@ struct platform_ldo { struct platform_configs { struct platform_gpio gpio; struct platform_ldo ldo; + const char *clk_src_name; + /* NFC_CLK pin voting state */ + bool clk_pin_voting; const char *szone; #ifdef NFC_SECURE_PERIPHERAL_ENABLED bool CNSS_NFC_HW_SECURE_ENABLE; @@ -283,6 +287,10 @@ struct nfc_dev { /*secure zone state*/ bool secure_zone; + /* CLK control */ + bool clk_run; + struct clk *s_clk; + void *ipcl; /* function pointers for the common i2c functionality */ @@ -318,6 +326,8 @@ int nfc_ese_pwr(struct nfc_dev *nfc_dev, unsigned long arg); int nfc_ldo_unvote(struct nfc_dev *nfc_dev); int is_nfc_data_available_for_read(struct nfc_dev *nfc_dev); int validate_nfc_state_nci(struct nfc_dev *nfc_dev); +int nfc_clock_select(struct nfc_dev *nfc_dev); +int nfc_clock_deselect(struct nfc_dev *nfc_dev); int nfc_post_init(struct nfc_dev *nfc_dev); int nfc_dynamic_protection_ioctl(struct nfc_dev *nfc_dev, unsigned long sec_zone_trans); bool nfc_hw_secure_check(void); diff --git a/nfc/common_qcom.c b/nfc/common_qcom.c index 7ca25b22dc..1e35e63096 100644 --- a/nfc/common_qcom.c +++ b/nfc/common_qcom.c @@ -4,7 +4,7 @@ * ***************************************************************************/ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * ***************************************************************************/ @@ -162,3 +162,43 @@ int nfc_ldo_unvote(struct nfc_dev *nfc_dev) return ret; } +/* + * Routine to enable clock. + * this routine can be extended to select from multiple + * sources based on clk name. + */ +int nfc_clock_select(struct nfc_dev *nfc_dev) +{ + int r = 0; + + nfc_dev->s_clk = clk_get(&nfc_dev->i2c_dev.client->dev, "nfc_ref_clk"); + + if (IS_ERR(nfc_dev->s_clk)) + return PTR_ERR(nfc_dev->s_clk); + + if (!nfc_dev->clk_run) + r = clk_prepare_enable(nfc_dev->s_clk); + + if (r) + return r; + + nfc_dev->clk_run = true; + return r; +} + +/* + * Routine to disable clocks + */ +int nfc_clock_deselect(struct nfc_dev *nfc_dev) +{ + int r = -EINVAL; + + if (nfc_dev->s_clk != NULL) { + if (nfc_dev->clk_run) { + clk_disable_unprepare(nfc_dev->s_clk); + nfc_dev->clk_run = false; + } + return 0; + } + return r; +} diff --git a/nfc/i2c_drv.c b/nfc/i2c_drv.c index 9acd14aed9..4bf45e7b74 100644 --- a/nfc/i2c_drv.c +++ b/nfc/i2c_drv.c @@ -30,12 +30,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ****************************************************************************/ /* - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved. * ****************************************************************************/ @@ -435,6 +432,12 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) nfc_dev->secure_zone = false; nfc_post_init(nfc_dev); #endif + + if (nfc_dev->configs.clk_pin_voting) + nfc_dev->clk_run = false; + else + nfc_dev->clk_run = true; + device_init_wakeup(&client->dev, true); i2c_set_clientdata(client, nfc_dev); i2c_dev->irq_wake_up = false; diff --git a/nfc_kernel_dlkm_vendor_board.mk b/nfc_kernel_dlkm_vendor_board.mk index 05cbb29090..d50b91b595 100644 --- a/nfc_kernel_dlkm_vendor_board.mk +++ b/nfc_kernel_dlkm_vendor_board.mk @@ -12,11 +12,11 @@ endif ########## Build kernel module based on local DLKM flag status ########## ifeq ($(NFC_DLKM_ENABLED), true) -ifeq ($(call is-board-platform-in-list, pineapple blair),true) +ifeq ($(call is-board-platform-in-list, pineapple blair pitti),true) BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/nxp-nci.ko endif endif -ifeq ($(call is-board-platform-in-list, blair),true) +ifeq ($(call is-board-platform-in-list, blair pitti),true) TARGET_ENABLE_PERIPHERAL_CONTROL := false endif