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
这个提交包含在:
27
nfc/common.c
27
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__,
|
pr_warn("%s: nfc dwl_req gpio invalid %d\n", __func__,
|
||||||
nfc_gpio->dwl_req);
|
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,
|
pr_info("%s: irq %d, ven %d, dwl %d\n", __func__, nfc_gpio->irq, nfc_gpio->ven,
|
||||||
nfc_gpio->dwl_req);
|
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;
|
nfc_dev->nfc_state = NFC_STATE_NCI;
|
||||||
|
|
||||||
} else if (arg == NFC_ENABLE) {
|
} else if (arg == NFC_ENABLE) {
|
||||||
/*
|
if(nfc_dev->configs.clk_pin_voting) {
|
||||||
* Setting flag true when NFC is enabled
|
/* 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;
|
nfc_dev->cold_reset.is_nfc_enabled = true;
|
||||||
} else if (arg == NFC_DISABLE) {
|
} else if (arg == NFC_DISABLE) {
|
||||||
/*
|
if(nfc_dev->configs.clk_pin_voting) {
|
||||||
* Setting flag true when NFC is disabled
|
/* 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;
|
nfc_dev->cold_reset.is_nfc_enabled = false;
|
||||||
} else {
|
} else {
|
||||||
pr_err("%s bad arg %lu\n", __func__, arg);
|
pr_err("%s bad arg %lu\n", __func__, arg);
|
||||||
|
11
nfc/common.h
11
nfc/common.h
@@ -28,6 +28,7 @@
|
|||||||
#include <linux/of_gpio.h>
|
#include <linux/of_gpio.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/ipc_logging.h>
|
#include <linux/ipc_logging.h>
|
||||||
|
#include <linux/clk.h>
|
||||||
#include <nfcinfo.h>
|
#include <nfcinfo.h>
|
||||||
#include "i2c_drv.h"
|
#include "i2c_drv.h"
|
||||||
#include "ese_cold_reset.h"
|
#include "ese_cold_reset.h"
|
||||||
@@ -111,6 +112,7 @@
|
|||||||
#define DTS_IRQ_GPIO_STR "qcom,sn-irq"
|
#define DTS_IRQ_GPIO_STR "qcom,sn-irq"
|
||||||
#define DTS_VEN_GPIO_STR "qcom,sn-ven"
|
#define DTS_VEN_GPIO_STR "qcom,sn-ven"
|
||||||
#define DTS_FWDN_GPIO_STR "qcom,sn-firm"
|
#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_DT_NAME "qcom,sn-vdd-1p8"
|
||||||
#define NFC_LDO_SUPPLY_NAME "qcom,sn-vdd-1p8-supply"
|
#define NFC_LDO_SUPPLY_NAME "qcom,sn-vdd-1p8-supply"
|
||||||
#define NFC_LDO_VOL_DT_NAME "qcom,sn-vdd-1p8-voltage"
|
#define NFC_LDO_VOL_DT_NAME "qcom,sn-vdd-1p8-voltage"
|
||||||
@@ -221,6 +223,9 @@ struct platform_ldo {
|
|||||||
struct platform_configs {
|
struct platform_configs {
|
||||||
struct platform_gpio gpio;
|
struct platform_gpio gpio;
|
||||||
struct platform_ldo ldo;
|
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;
|
union nqx_uinfo nqx_info;
|
||||||
|
|
||||||
|
/* CLK control */
|
||||||
|
bool clk_run;
|
||||||
|
struct clk *s_clk;
|
||||||
|
|
||||||
void *ipcl;
|
void *ipcl;
|
||||||
|
|
||||||
/* function pointers for the common i2c functionality */
|
/* 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 nfc_ldo_unvote(struct nfc_dev *nfc_dev);
|
||||||
int is_nfc_data_available_for_read(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 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_ */
|
#endif /* _COMMON_H_ */
|
||||||
|
@@ -161,3 +161,44 @@ int nfc_ldo_unvote(struct nfc_dev *nfc_dev)
|
|||||||
pr_err("%s: set load failed\n", __func__);
|
pr_err("%s: set load failed\n", __func__);
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
@@ -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);
|
pr_err("nfc hw check failed ret %d\n", ret);
|
||||||
goto err_nfcc_hw_check;
|
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, 1);
|
||||||
gpio_set_ven(nfc_dev, 0);
|
gpio_set_ven(nfc_dev, 0);
|
||||||
gpio_set_ven(nfc_dev, 1);
|
gpio_set_ven(nfc_dev, 1);
|
||||||
|
在新工单中引用
屏蔽一个用户