diff options
author | George Chang <georgekgchang@google.com> | 2021-04-23 19:20:38 +0800 |
---|---|---|
committer | George Chang <georgekgchang@google.com> | 2021-04-26 20:21:56 +0800 |
commit | 97017f50c4e9dcdb89eeb7910e3eac64e0555393 (patch) | |
tree | 30d4804e6347d63c2e5bd8d426d7adc750f78897 | |
parent | 992a91de71f29b480cfdcbe2f4986f18e56ffbc0 (diff) | |
download | nfc-97017f50c4e9dcdb89eeb7910e3eac64e0555393.tar.gz |
Add clock control ability in IOCTL
Turn on the clock at open and manage the clock on/off later by IOCTL.
NFC HAL would switch on/off clock when it requires the clock signal.
The NFC chip can't wait for clock delay more than 5 ms when requesting
then clock, but the clock signal enabled by the clk_req handler might
be delayed for more than 80 ms after clk_req goes high.
Bug: 183693317
Test: on/off clock and get reg value via ioctl
Signed-off-by: George Chang <georgekgchang@google.com>
Change-Id: Ia51b269f0a521f3af6e0a0814531f0c35e152b37
-rw-r--r-- | st21nfc.c | 63 | ||||
-rw-r--r-- | st21nfc.h | 3 |
2 files changed, 50 insertions, 16 deletions
@@ -37,8 +37,9 @@ #define IDLE_CHARACTER 0x7e #define ST21NFC_POWER_STATE_MAX 3 #define WAKEUP_SRC_TIMEOUT (2000) +#define EXYNOS_CLK_MASK 0x01 -#define DRIVER_VERSION "2.0.16" +#define DRIVER_VERSION "2.0.17" #define PROP_PWR_MON_RW_ON_NTF nci_opcode_pack(NCI_GID_PROPRIETARY, 5) #define PROP_PWR_MON_RW_OFF_NTF nci_opcode_pack(NCI_GID_PROPRIETARY, 6) @@ -182,6 +183,20 @@ static int st21nfc_clock_deselect(struct st21nfc_device *st21nfc_dev) return 0; } +static void st21nfc_exynos_clk_control(struct st21nfc_device *st21nfc_dev, + bool enable) +{ + if (st21nfc_dev->clk_pad) { + if (enable) { + exynos_pmu_update(st21nfc_dev->clk_pad, EXYNOS_CLK_MASK, + 1); + } else { + exynos_pmu_update(st21nfc_dev->clk_pad, EXYNOS_CLK_MASK, + 0); + } + } +} + static irqreturn_t st21nfc_clkreq_irq_handler(int irq, void *dev_id) { struct st21nfc_device *st21nfc_dev = dev_id; @@ -189,11 +204,10 @@ static irqreturn_t st21nfc_clkreq_irq_handler(int irq, void *dev_id) if (st21nfc_dev->pinctrl_en) { if (value) - exynos_pmu_update(st21nfc_dev->clk_pad, 1, 1); + st21nfc_exynos_clk_control(st21nfc_dev, true); else - exynos_pmu_update(st21nfc_dev->clk_pad, 1, 0); + st21nfc_exynos_clk_control(st21nfc_dev, false); } - return IRQ_HANDLED; } @@ -552,10 +566,11 @@ static int st21nfc_dev_open(struct inode *inode, struct file *filp) if (st21nfc_dev->device_open) { ret = -EBUSY; - dev_err(&st21nfc_dev->client->dev, - "%s : device already opened ret= %d\n", __func__, ret); } else { st21nfc_dev->device_open = true; + if (st21nfc_dev->clk_pad) { + st21nfc_exynos_clk_control(st21nfc_dev, true); + } } return ret; } @@ -568,6 +583,9 @@ static int st21nfc_release(struct inode *inode, struct file *file) st21nfc_device); st21nfc_dev->device_open = false; + if (st21nfc_dev->clk_pad) { + st21nfc_exynos_clk_control(st21nfc_dev, false); + } return 0; } @@ -672,6 +690,20 @@ static long st21nfc_dev_ioctl(struct file *filp, unsigned int cmd, ret = -ENODEV; } break; + case ST21NFC_CLK_ENABLE: + st21nfc_exynos_clk_control(st21nfc_dev, true); + break; + case ST21NFC_CLK_DISABLE: + st21nfc_exynos_clk_control(st21nfc_dev, false); + break; + case ST21NFC_CLK_STATE: + if (st21nfc_dev->clk_pad == 0 || + exynos_pmu_read(st21nfc_dev->clk_pad, &ret) < 0) { + ret = -ENODEV; + } else { + ret &= EXYNOS_CLK_MASK; + } + break; default: dev_err(&st21nfc_dev->client->dev, "%s bad ioctl %u\n", __func__, cmd); @@ -1002,16 +1034,15 @@ static int st21nfc_probe(struct i2c_client *client, } } - /* Set clk_run when clock pinctrl already enabled */ - if (st21nfc_dev->pinctrl_en != 0) { - if (device_property_read_u32(dev, - "pmu_clk_pad", - &st21nfc_dev->clk_pad)) { - dev_err(dev, - "%s : PMU_CLKOUT_PAD offset is unset\n", - __func__); - st21nfc_dev->pinctrl_en = 0; - } + /* Get clk_pad value*/ + if (device_property_read_u32(dev, + "pmu_clk_pad", + &st21nfc_dev->clk_pad)) { + dev_err(dev, + "%s : PMU_CLKOUT_PAD offset is unset\n", + __func__); + st21nfc_dev->clk_pad = 0; + st21nfc_dev->pinctrl_en = 0; } ret = st21nfc_clock_select(st21nfc_dev); @@ -21,5 +21,8 @@ #define ST21NFC_SET_POLARITY_HIGH _IOR(ST21NFC_MAGIC, 0x05, unsigned int) #define ST21NFC_GET_POLARITY _IOR(ST21NFC_MAGIC, 0x07, unsigned int) #define ST21NFC_RECOVERY _IOR(ST21NFC_MAGIC, 0x08, unsigned int) +#define ST21NFC_CLK_ENABLE _IOR(ST21NFC_MAGIC, 0x11, unsigned int) +#define ST21NFC_CLK_DISABLE _IOR(ST21NFC_MAGIC, 0x12, unsigned int) +#define ST21NFC_CLK_STATE _IOR(ST21NFC_MAGIC, 0x13, unsigned int) #endif |