From 414ee1d6684ec2e1ed62c99f63bff05a93e2224c Mon Sep 17 00:00:00 2001 From: Khageswararao Rao B Date: Thu, 17 Feb 2022 14:54:11 +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: Id617efb53ba06caa735927b4d271990be7e4766c --- nfc/common.c | 27 +++++++++++++++++++++------ nfc/common.h | 11 +++++++++++ nfc/common_qcom.c | 41 +++++++++++++++++++++++++++++++++++++++++ nfc/i2c_drv.c | 6 ++++++ 4 files changed, 79 insertions(+), 6 deletions(-) diff --git a/nfc/common.c b/nfc/common.c index c9b37cdcbb..6a1f5329d8 100644 --- a/nfc/common.c +++ b/nfc/common.c @@ -66,6 +66,13 @@ int nfc_parse_dt(struct device *dev, struct platform_configs *nfc_configs, pr_warn("%s: nfc dwl_req gpio invalid %d\n", __func__, nfc_gpio->dwl_req); + if (of_property_read_string(np, DTS_CLKSRC_GPIO_STR, &nfc_configs->clk_src_name)) { + nfc_configs->clk_pin_voting = false; + } + else { + nfc_configs->clk_pin_voting = true; + } + pr_info("%s: irq %d, ven %d, dwl %d\n", __func__, nfc_gpio->irq, nfc_gpio->ven, nfc_gpio->dwl_req); @@ -329,14 +336,22 @@ 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) { - /* - * Setting flag true when NFC is enabled - */ + 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) { - /* - * Setting flag true when NFC is disabled - */ + 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 { pr_err("%s bad arg %lu\n", __func__, arg); diff --git a/nfc/common.h b/nfc/common.h index 1c723bf79c..29c0c49028 100644 --- a/nfc/common.h +++ b/nfc/common.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include "i2c_drv.h" #include "ese_cold_reset.h" @@ -111,6 +112,7 @@ #define DTS_IRQ_GPIO_STR "qcom,sn-irq" #define DTS_VEN_GPIO_STR "qcom,sn-ven" #define DTS_FWDN_GPIO_STR "qcom,sn-firm" +#define DTS_CLKSRC_GPIO_STR "qcom,clk-src" #define NFC_LDO_SUPPLY_DT_NAME "qcom,sn-vdd-1p8" #define NFC_LDO_SUPPLY_NAME "qcom,sn-vdd-1p8-supply" #define NFC_LDO_VOL_DT_NAME "qcom,sn-vdd-1p8-voltage" @@ -221,6 +223,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; }; @@ -261,6 +266,10 @@ struct nfc_dev { union nqx_uinfo nqx_info; + /* CLK control */ + bool clk_run; + struct clk *s_clk; + void *ipcl; /* function pointers for the common i2c functionality */ @@ -296,4 +305,6 @@ 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); #endif /* _COMMON_H_ */ diff --git a/nfc/common_qcom.c b/nfc/common_qcom.c index ef05d01394..9ba42863ad 100644 --- a/nfc/common_qcom.c +++ b/nfc/common_qcom.c @@ -161,3 +161,44 @@ int nfc_ldo_unvote(struct nfc_dev *nfc_dev) pr_err("%s: set load failed\n", __func__); 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 d0e2d5a5f2..4ab1f00063 100644 --- a/nfc/i2c_drv.c +++ b/nfc/i2c_drv.c @@ -431,6 +431,12 @@ int nfc_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id) pr_err("nfc hw check failed ret %d\n", ret); goto err_nfcc_hw_check; } + + if(nfc_dev->configs.clk_pin_voting) + nfc_dev->clk_run = false; + else + nfc_dev->clk_run = true; + gpio_set_ven(nfc_dev, 1); gpio_set_ven(nfc_dev, 0); gpio_set_ven(nfc_dev, 1);