linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
Search results ordered by [date|relevance]  view[summary|nested|Atom feed]
thread overview below | download mbox.gz: |
* [PATCH net-next 1/3] nfc: s3fwrn5: Remove the max_payload
       [not found]     <CGME20201116011205epcms2p566dbc946d6c7a0198d09b3a872e85f33@epcms2p5>
@ 2020-11-16  1:12 95% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-16  1:12 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

max_payload is unused.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/core.c    | 3 +--
 drivers/nfc/s3fwrn5/i2c.c     | 4 +---
 drivers/nfc/s3fwrn5/s3fwrn5.h | 3 +--
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c
index ba6c486d6465..f8e5d78d9078 100644
--- a/drivers/nfc/s3fwrn5/core.c
+++ b/drivers/nfc/s3fwrn5/core.c
@@ -136,7 +136,7 @@ static struct nci_ops s3fwrn5_nci_ops = {
 };
 
 int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
-	const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload)
+	const struct s3fwrn5_phy_ops *phy_ops)
 {
 	struct s3fwrn5_info *info;
 	int ret;
@@ -148,7 +148,6 @@ int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
 	info->phy_id = phy_id;
 	info->pdev = pdev;
 	info->phy_ops = phy_ops;
-	info->max_payload = max_payload;
 	mutex_init(&info->mutex);
 
 	s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index dc995286be84..0ffa389066a0 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -19,7 +19,6 @@
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_I2C_MAX_PAYLOAD 32
 #define S3FWRN5_EN_WAIT_TIME 150
 
 struct s3fwrn5_i2c_phy {
@@ -248,8 +247,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops,
-		S3FWRN5_I2C_MAX_PAYLOAD);
+	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/nfc/s3fwrn5/s3fwrn5.h b/drivers/nfc/s3fwrn5/s3fwrn5.h
index ede68bb5eeae..9d5f34759225 100644
--- a/drivers/nfc/s3fwrn5/s3fwrn5.h
+++ b/drivers/nfc/s3fwrn5/s3fwrn5.h
@@ -34,7 +34,6 @@ struct s3fwrn5_info {
 	struct device *pdev;
 
 	const struct s3fwrn5_phy_ops *phy_ops;
-	unsigned int max_payload;
 
 	struct s3fwrn5_fw_info fw_info;
 
@@ -79,7 +78,7 @@ static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
 }
 
 int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
-	const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload);
+	const struct s3fwrn5_phy_ops *phy_ops);
 void s3fwrn5_remove(struct nci_dev *ndev);
 
 int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
-- 
2.17.1


^ permalink raw reply related	[relevance 95%]

* [PATCH net-next 2/3] nfc: s3fwrn5: Fix the misspelling in a comment
       [not found]     <CGME20201116011755epcms2p7f7232e0865e8e1bc11a4b528c10d3571@epcms2p7>
@ 2020-11-16  1:17 99% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-16  1:17 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

stucture should be replaced by structure.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/firmware.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
index ec930ee2c847..4cde6dd5c019 100644
--- a/drivers/nfc/s3fwrn5/firmware.c
+++ b/drivers/nfc/s3fwrn5/firmware.c
@@ -266,7 +266,7 @@ static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info)
 }
 
 /*
- * Firmware header stucture:
+ * Firmware header structure:
  *
  * 0x00 - 0x0B : Date and time string (w/o NUL termination)
  * 0x10 - 0x13 : Firmware version
-- 
2.17.1


^ permalink raw reply related	[relevance 99%]

* [PATCH net-next 3/3] nfc: s3fwrn5: Change the error code
       [not found]     <CGME20201116011950epcms2p68117cc4a7228db2baecb7d4a4840b955@epcms2p6>
@ 2020-11-16  1:19 99% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-16  1:19 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/s3fwrn5.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/s3fwrn5.h b/drivers/nfc/s3fwrn5/s3fwrn5.h
index 9d5f34759225..bb8f936d13a2 100644
--- a/drivers/nfc/s3fwrn5/s3fwrn5.h
+++ b/drivers/nfc/s3fwrn5/s3fwrn5.h
@@ -44,7 +44,7 @@ static inline int s3fwrn5_set_mode(struct s3fwrn5_info *info,
 	enum s3fwrn5_mode mode)
 {
 	if (!info->phy_ops->set_mode)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	info->phy_ops->set_mode(info->phy_id, mode);
 
@@ -54,7 +54,7 @@ static inline int s3fwrn5_set_mode(struct s3fwrn5_info *info,
 static inline enum s3fwrn5_mode s3fwrn5_get_mode(struct s3fwrn5_info *info)
 {
 	if (!info->phy_ops->get_mode)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return info->phy_ops->get_mode(info->phy_id);
 }
@@ -62,7 +62,7 @@ static inline enum s3fwrn5_mode s3fwrn5_get_mode(struct s3fwrn5_info *info)
 static inline int s3fwrn5_set_wake(struct s3fwrn5_info *info, bool wake)
 {
 	if (!info->phy_ops->set_wake)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	info->phy_ops->set_wake(info->phy_id, wake);
 
@@ -72,7 +72,7 @@ static inline int s3fwrn5_set_wake(struct s3fwrn5_info *info, bool wake)
 static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
 {
 	if (!info->phy_ops->write)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return info->phy_ops->write(info->phy_id, skb);
 }
-- 
2.17.1


^ permalink raw reply related	[relevance 99%]

* [PATCH net-next v2 0/3] nfc: s3fwrn5: Refactor the s3fwrn5 driver
       [not found]     <CGME20201117011420epcms2p28407a6596fdf1e63cb84af98fa768566@epcms2p2>
@ 2020-11-17  1:14 99% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17  1:14 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak, Bongsu Jeon; +Cc: linux-nfc, netdev, linux-kernel

Changes from v1:
- Remove the trailing dot from subject.
- Remove an empty line at beginning of commit message.
- Add a commit message.

Bongsu Jeon (3):
  nfc: s3fwrn5: Remove the max_payload
  nfc: s3fwrn5: Fix the misspelling in a comment
  nfc: s3fwrn5: Change the error code

 drivers/nfc/s3fwrn5/core.c     |  3 +--
 drivers/nfc/s3fwrn5/firmware.c |  2 +-
 drivers/nfc/s3fwrn5/i2c.c      |  4 +---
 drivers/nfc/s3fwrn5/s3fwrn5.h  | 11 +++++------
 4 files changed, 8 insertions(+), 12 deletions(-)

-- 
2.17.1


^ permalink raw reply	[relevance 99%]

* [PATCH net-next v2 1/3] nfc: s3fwrn5: Remove the max_payload
       [not found]     <CGME20201117011611epcms2p22fb0315814144e94856a96014c376a04@epcms2p2>
@ 2020-11-17  1:16 95% ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-17  1:16 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

max_payload is unused.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/core.c    | 3 +--
 drivers/nfc/s3fwrn5/i2c.c     | 4 +---
 drivers/nfc/s3fwrn5/s3fwrn5.h | 3 +--
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c
index ba6c486d6465..f8e5d78d9078 100644
--- a/drivers/nfc/s3fwrn5/core.c
+++ b/drivers/nfc/s3fwrn5/core.c
@@ -136,7 +136,7 @@ static struct nci_ops s3fwrn5_nci_ops = {
 };
 
 int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
-	const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload)
+	const struct s3fwrn5_phy_ops *phy_ops)
 {
 	struct s3fwrn5_info *info;
 	int ret;
@@ -148,7 +148,6 @@ int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
 	info->phy_id = phy_id;
 	info->pdev = pdev;
 	info->phy_ops = phy_ops;
-	info->max_payload = max_payload;
 	mutex_init(&info->mutex);
 
 	s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index dc995286be84..0ffa389066a0 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -19,7 +19,6 @@
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_I2C_MAX_PAYLOAD 32
 #define S3FWRN5_EN_WAIT_TIME 150
 
 struct s3fwrn5_i2c_phy {
@@ -248,8 +247,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops,
-		S3FWRN5_I2C_MAX_PAYLOAD);
+	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/nfc/s3fwrn5/s3fwrn5.h b/drivers/nfc/s3fwrn5/s3fwrn5.h
index ede68bb5eeae..9d5f34759225 100644
--- a/drivers/nfc/s3fwrn5/s3fwrn5.h
+++ b/drivers/nfc/s3fwrn5/s3fwrn5.h
@@ -34,7 +34,6 @@ struct s3fwrn5_info {
 	struct device *pdev;
 
 	const struct s3fwrn5_phy_ops *phy_ops;
-	unsigned int max_payload;
 
 	struct s3fwrn5_fw_info fw_info;
 
@@ -79,7 +78,7 @@ static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
 }
 
 int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
-	const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload);
+	const struct s3fwrn5_phy_ops *phy_ops);
 void s3fwrn5_remove(struct nci_dev *ndev);
 
 int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
-- 
2.17.1


^ permalink raw reply related	[relevance 95%]

* [PATCH net-next v2 2/3] nfc: s3fwrn5: Fix the misspelling in a comment
       [not found]     <CGME20201117011742epcms2p1fb85ba231b3a1673d97af4bc1479744f@epcms2p1>
@ 2020-11-17  1:17 99% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17  1:17 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

stucture should be replaced by structure.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/firmware.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
index ec930ee2c847..4cde6dd5c019 100644
--- a/drivers/nfc/s3fwrn5/firmware.c
+++ b/drivers/nfc/s3fwrn5/firmware.c
@@ -266,7 +266,7 @@ static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info)
 }
 
 /*
- * Firmware header stucture:
+ * Firmware header structure:
  *
  * 0x00 - 0x0B : Date and time string (w/o NUL termination)
  * 0x10 - 0x13 : Firmware version
-- 
2.17.1


^ permalink raw reply related	[relevance 99%]

* [PATCH net-next v2 3/3] nfc: s3fwrn5: Change the error code
       [not found]     <CGME20201117011850epcms2p568af074144630cd0f02b3a7f7eff8d1a@epcms2p5>
@ 2020-11-17  1:18 99% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17  1:18 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/s3fwrn5.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/s3fwrn5.h b/drivers/nfc/s3fwrn5/s3fwrn5.h
index 9d5f34759225..bb8f936d13a2 100644
--- a/drivers/nfc/s3fwrn5/s3fwrn5.h
+++ b/drivers/nfc/s3fwrn5/s3fwrn5.h
@@ -44,7 +44,7 @@ static inline int s3fwrn5_set_mode(struct s3fwrn5_info *info,
 	enum s3fwrn5_mode mode)
 {
 	if (!info->phy_ops->set_mode)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	info->phy_ops->set_mode(info->phy_id, mode);
 
@@ -54,7 +54,7 @@ static inline int s3fwrn5_set_mode(struct s3fwrn5_info *info,
 static inline enum s3fwrn5_mode s3fwrn5_get_mode(struct s3fwrn5_info *info)
 {
 	if (!info->phy_ops->get_mode)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return info->phy_ops->get_mode(info->phy_id);
 }
@@ -62,7 +62,7 @@ static inline enum s3fwrn5_mode s3fwrn5_get_mode(struct s3fwrn5_info *info)
 static inline int s3fwrn5_set_wake(struct s3fwrn5_info *info, bool wake)
 {
 	if (!info->phy_ops->set_wake)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	info->phy_ops->set_wake(info->phy_id, wake);
 
@@ -72,7 +72,7 @@ static inline int s3fwrn5_set_wake(struct s3fwrn5_info *info, bool wake)
 static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
 {
 	if (!info->phy_ops->write)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return info->phy_ops->write(info->phy_id, skb);
 }
-- 
2.17.1


^ permalink raw reply related	[relevance 99%]

* [PATCH net-next] net/nfc/nci: Support NCI 2.x initial sequence
       [not found]     <CGME20201117053759epcms2p80e47c3e9be01d564c775c045a42678f7@epcms2p8>
@ 2020-11-17  5:37 75% ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-17  5:37 UTC (permalink / raw)
  To: davem, kuba; +Cc: netdev, linux-kernel

implement the NCI 2.x initial sequence to support NCI 2.x NFCC.
Since NCI 2.0, CORE_RESET and CORE_INIT sequence have been changed.
If NFCEE supports NCI 2.x, then NCI 2.x initial sequence will work.

In NCI 1.0, Initial sequence and payloads are as below:
(DH)                     (NFCC)
 |  -- CORE_RESET_CMD --> |
 |  <-- CORE_RESET_RSP -- |
 |  -- CORE_INIT_CMD -->  |
 |  <-- CORE_INIT_RSP --  |
 CORE_RESET_RSP payloads are Status, NCI version, Configuration Status.
 CORE_INIT_CMD payloads are empty.
 CORE_INIT_RSP payloads are Status, NFCC Features,
    Number of Supported RF Interfaces, Supported RF Interface,
    Max Logical Connections, Max Routing table Size,
    Max Control Packet Payload Size, Max Size for Large Parameters,
    Manufacturer ID, Manufacturer Specific Information.

In NCI 2.0, Initial Sequence and Parameters are as below:
(DH)                     (NFCC)
 |  -- CORE_RESET_CMD --> |
 |  <-- CORE_RESET_RSP -- |
 |  <-- CORE_RESET_NTF -- |
 |  -- CORE_INIT_CMD -->  |
 |  <-- CORE_INIT_RSP --  |
 CORE_RESET_RSP payloads are Status.
 CORE_RESET_NTF payloads are Reset Trigger,
    Configuration Status, NCI Version, Manufacturer ID,
    Manufacturer Specific Information Length,
    Manufacturer Specific Information.
 CORE_INIT_CMD payloads are Feature1, Feature2.
 CORE_INIT_RSP payloads are Status, NFCC Features,
    Max Logical Connections, Max Routing Table Size,
    Max Control Packet Payload Size,
    Max Data Packet Payload Size of the Static HCI Connection,
    Number of Credits of the Static HCI Connection,
    Max NFC-V RF Frame Size, Number of Supported RF Interfaces,
    Supported RF Interfaces.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 include/net/nfc/nci.h | 39 ++++++++++++++++++++++
 net/nfc/nci/core.c    | 23 +++++++++++--
 net/nfc/nci/ntf.c     | 21 ++++++++++++
 net/nfc/nci/rsp.c     | 75 +++++++++++++++++++++++++++++++++++++------
 4 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index 0550e0380b8d..b434f984bc8c 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -25,6 +25,8 @@
 #define NCI_MAX_PARAM_LEN					251
 #define NCI_MAX_PAYLOAD_SIZE					255
 #define NCI_MAX_PACKET_SIZE					258
+#define NCI_MAX_LARGE_PARAMS_NCI_v2				15
+#define NCI_VER_2_MASK						0x20
 
 /* NCI Status Codes */
 #define NCI_STATUS_OK						0x00
@@ -131,6 +133,9 @@
 #define NCI_LF_CON_BITR_F_212					0x02
 #define NCI_LF_CON_BITR_F_424					0x04
 
+/* NCI 2.x Feature Enable Bit */
+#define NCI_FEATURE_DISABLE					0x00
+
 /* NCI Reset types */
 #define NCI_RESET_TYPE_KEEP_CONFIG				0x00
 #define NCI_RESET_TYPE_RESET_CONFIG				0x01
@@ -220,6 +225,11 @@ struct nci_core_reset_cmd {
 } __packed;
 
 #define NCI_OP_CORE_INIT_CMD		nci_opcode_pack(NCI_GID_CORE, 0x01)
+/* To support NCI 2.x */
+struct nci_core_init_v2_cmd {
+	__u8	feature1;
+	__u8	feature2;
+} __packed;
 
 #define NCI_OP_CORE_SET_CONFIG_CMD	nci_opcode_pack(NCI_GID_CORE, 0x02)
 struct set_config_param {
@@ -316,6 +326,11 @@ struct nci_core_reset_rsp {
 	__u8	config_status;
 } __packed;
 
+/* To support NCI ver 2.x */
+struct nci_core_reset_rsp_nci_ver2 {
+	__u8	status;
+} __packed;
+
 #define NCI_OP_CORE_INIT_RSP		nci_opcode_pack(NCI_GID_CORE, 0x01)
 struct nci_core_init_rsp_1 {
 	__u8	status;
@@ -334,6 +349,20 @@ struct nci_core_init_rsp_2 {
 	__le32	manufact_specific_info;
 } __packed;
 
+/* To support NCI ver 2.x */
+struct nci_core_init_rsp_nci_ver2 {
+	__u8	status;
+	__le32	nfcc_features;
+	__u8	max_logical_connections;
+	__le16	max_routing_table_size;
+	__u8	max_ctrl_pkt_payload_len;
+	__u8	max_data_pkt_hci_payload_len;
+	__u8	number_of_hci_credit;
+	__le16	max_nfc_v_frame_size;
+	__u8	num_supported_rf_interfaces;
+	__u8	supported_rf_interfaces[];
+} __packed;
+
 #define NCI_OP_CORE_SET_CONFIG_RSP	nci_opcode_pack(NCI_GID_CORE, 0x02)
 struct nci_core_set_config_rsp {
 	__u8	status;
@@ -372,6 +401,16 @@ struct nci_nfcee_discover_rsp {
 /* --------------------------- */
 /* ---- NCI Notifications ---- */
 /* --------------------------- */
+#define NCI_OP_CORE_RESET_NTF		nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_ntf {
+	__u8	reset_trigger;
+	__u8	config_status;
+	__u8	nci_ver;
+	__u8	manufact_id;
+	__u8	manufacturer_specific_len;
+	__u32	manufact_specific_info;
+} __packed;
+
 #define NCI_OP_CORE_CONN_CREDITS_NTF	nci_opcode_pack(NCI_GID_CORE, 0x06)
 struct conn_credit_entry {
 	__u8	conn_id;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 4953ee5146e1..68889faadda2 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -165,7 +165,14 @@ static void nci_reset_req(struct nci_dev *ndev, unsigned long opt)
 
 static void nci_init_req(struct nci_dev *ndev, unsigned long opt)
 {
-	nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+	struct nci_core_init_v2_cmd *cmd = (struct nci_core_init_v2_cmd *)opt;
+
+	if (!cmd) {
+		nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+	} else {
+		/* if nci version is 2.0, then use the feature parameters */
+		nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, sizeof(struct nci_core_init_v2_cmd), cmd);
+	}
 }
 
 static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
@@ -497,8 +504,18 @@ static int nci_open_device(struct nci_dev *ndev)
 	}
 
 	if (!rc) {
-		rc = __nci_request(ndev, nci_init_req, 0,
-				   msecs_to_jiffies(NCI_INIT_TIMEOUT));
+		if (!(ndev->nci_ver & NCI_VER_2_MASK)) {
+			rc = __nci_request(ndev, nci_init_req, 0,
+					   msecs_to_jiffies(NCI_INIT_TIMEOUT));
+		} else {
+			struct nci_core_init_v2_cmd nci_init_v2_cmd;
+
+			nci_init_v2_cmd.feature1 = NCI_FEATURE_DISABLE;
+			nci_init_v2_cmd.feature2 = NCI_FEATURE_DISABLE;
+
+			rc = __nci_request(ndev, nci_init_req, (unsigned long)&nci_init_v2_cmd,
+					   msecs_to_jiffies(NCI_INIT_TIMEOUT));
+		}
 	}
 
 	if (!rc && ndev->ops->post_setup)
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 33e1170817f0..98af04c86b2c 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -27,6 +27,23 @@
 
 /* Handle NCI Notification packets */
 
+static void nci_core_reset_ntf_packet(struct nci_dev *ndev,
+				      struct sk_buff *skb)
+{
+	/* Handle NCI 2.x core reset notification */
+	struct nci_core_reset_ntf *ntf = (void *)skb->data;
+
+	ndev->nci_ver = ntf->nci_ver;
+	pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+		 ntf->nci_ver, ntf->config_status);
+
+	ndev->manufact_id = ntf->manufact_id;
+	ndev->manufact_specific_info =
+		__le32_to_cpu(ntf->manufact_specific_info);
+
+	nci_req_complete(ndev, NCI_STATUS_OK);
+}
+
 static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
 					     struct sk_buff *skb)
 {
@@ -756,6 +773,10 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	}
 
 	switch (ntf_opcode) {
+	case NCI_OP_CORE_RESET_NTF:
+		nci_core_reset_ntf_packet(ndev, skb);
+		break;
+
 	case NCI_OP_CORE_CONN_CREDITS_NTF:
 		nci_core_conn_credits_ntf_packet(ndev, skb);
 		break;
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index a48297b79f34..dcb371d7923b 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -31,16 +31,19 @@ static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 
 	pr_debug("status 0x%x\n", rsp->status);
 
-	if (rsp->status == NCI_STATUS_OK) {
-		ndev->nci_ver = rsp->nci_ver;
-		pr_debug("nci_ver 0x%x, config_status 0x%x\n",
-			 rsp->nci_ver, rsp->config_status);
-	}
+	/* Handle NCI 1.x ver */
+	if (skb->len != 1) {
+		if (rsp->status == NCI_STATUS_OK) {
+			ndev->nci_ver = rsp->nci_ver;
+			pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+				 rsp->nci_ver, rsp->config_status);
+		}
 
-	nci_req_complete(ndev, rsp->status);
+		nci_req_complete(ndev, rsp->status);
+	}
 }
 
-static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+static __u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
 	struct nci_core_init_rsp_2 *rsp_2;
@@ -48,7 +51,7 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	pr_debug("status 0x%x\n", rsp_1->status);
 
 	if (rsp_1->status != NCI_STATUS_OK)
-		goto exit;
+		return rsp_1->status;
 
 	ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
 	ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
@@ -77,6 +80,60 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	ndev->manufact_specific_info =
 		__le32_to_cpu(rsp_2->manufact_specific_info);
 
+	return NCI_STATUS_OK;
+}
+
+static __u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
+	__u8 rf_interface_idx = 0;
+	__u8 rf_extension_cnt = 0;
+	__u8 *supported_rf_interface = rsp->supported_rf_interfaces;
+
+	pr_debug("status %x\n", rsp->status);
+
+	if (rsp->status != NCI_STATUS_OK)
+		return rsp->status;
+
+	ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
+	ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
+
+	if (ndev->num_supported_rf_interfaces >
+	    NCI_MAX_SUPPORTED_RF_INTERFACES) {
+		ndev->num_supported_rf_interfaces =
+			NCI_MAX_SUPPORTED_RF_INTERFACES;
+	}
+
+	while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
+		ndev->supported_rf_interfaces[rf_interface_idx] = *supported_rf_interface++;
+
+		/* skip rf extension parameters */
+		rf_extension_cnt = *supported_rf_interface++;
+		supported_rf_interface += rf_extension_cnt;
+	}
+
+	ndev->max_logical_connections = rsp->max_logical_connections;
+	ndev->max_routing_table_size =
+			__le16_to_cpu(rsp->max_routing_table_size);
+	ndev->max_ctrl_pkt_payload_len =
+			rsp->max_ctrl_pkt_payload_len;
+	ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2;
+
+	return NCI_STATUS_OK;
+}
+
+static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	__u8 status = 0;
+
+	if (!(ndev->nci_ver & NCI_VER_2_MASK))
+		status = nci_core_init_rsp_packet_v1(ndev, skb);
+	else
+		status = nci_core_init_rsp_packet_v2(ndev, skb);
+
+	if (status != NCI_STATUS_OK)
+		goto exit;
+
 	pr_debug("nfcc_features 0x%x\n",
 		 ndev->nfcc_features);
 	pr_debug("num_supported_rf_interfaces %d\n",
@@ -103,7 +160,7 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		 ndev->manufact_specific_info);
 
 exit:
-	nci_req_complete(ndev, rsp_1->status);
+	nci_req_complete(ndev, status);
 }
 
 static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
-- 
2.17.1


^ permalink raw reply related	[relevance 75%]

* [PATCH net-next v2 1/3] nfc: s3fwrn5: Remove the max_payload
       [not found]     <CGME20201117080824epcms2p36f70e06e2d8bd51d1af278b26ca65725@epcms2p3>
@ 2020-11-17  8:08 95% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17  8:08 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

max_payload is unused.

Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/core.c    | 3 +--
 drivers/nfc/s3fwrn5/i2c.c     | 4 +---
 drivers/nfc/s3fwrn5/s3fwrn5.h | 3 +--
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c
index ba6c486d6465..f8e5d78d9078 100644
--- a/drivers/nfc/s3fwrn5/core.c
+++ b/drivers/nfc/s3fwrn5/core.c
@@ -136,7 +136,7 @@ static struct nci_ops s3fwrn5_nci_ops = {
 };
 
 int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
-	const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload)
+	const struct s3fwrn5_phy_ops *phy_ops)
 {
 	struct s3fwrn5_info *info;
 	int ret;
@@ -148,7 +148,6 @@ int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
 	info->phy_id = phy_id;
 	info->pdev = pdev;
 	info->phy_ops = phy_ops;
-	info->max_payload = max_payload;
 	mutex_init(&info->mutex);
 
 	s3fwrn5_set_mode(info, S3FWRN5_MODE_COLD);
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index dc995286be84..0ffa389066a0 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -19,7 +19,6 @@
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_I2C_MAX_PAYLOAD 32
 #define S3FWRN5_EN_WAIT_TIME 150
 
 struct s3fwrn5_i2c_phy {
@@ -248,8 +247,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops,
-		S3FWRN5_I2C_MAX_PAYLOAD);
+	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
 	if (ret < 0)
 		return ret;
 
diff --git a/drivers/nfc/s3fwrn5/s3fwrn5.h b/drivers/nfc/s3fwrn5/s3fwrn5.h
index ede68bb5eeae..9d5f34759225 100644
--- a/drivers/nfc/s3fwrn5/s3fwrn5.h
+++ b/drivers/nfc/s3fwrn5/s3fwrn5.h
@@ -34,7 +34,6 @@ struct s3fwrn5_info {
 	struct device *pdev;
 
 	const struct s3fwrn5_phy_ops *phy_ops;
-	unsigned int max_payload;
 
 	struct s3fwrn5_fw_info fw_info;
 
@@ -79,7 +78,7 @@ static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
 }
 
 int s3fwrn5_probe(struct nci_dev **ndev, void *phy_id, struct device *pdev,
-	const struct s3fwrn5_phy_ops *phy_ops, unsigned int max_payload);
+	const struct s3fwrn5_phy_ops *phy_ops);
 void s3fwrn5_remove(struct nci_dev *ndev);
 
 int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb,
-- 
2.17.1


^ permalink raw reply related	[relevance 95%]

* [PATCH net-next v2 2/3] nfc: s3fwrn5: Fix the misspelling in a comment
       [not found]     <CGME20201117080950epcms2p4d332688ce351321c3222734bca680b57@epcms2p4>
@ 2020-11-17  8:09 99% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17  8:09 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

stucture should be replaced by structure.

Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/firmware.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
index ec930ee2c847..4cde6dd5c019 100644
--- a/drivers/nfc/s3fwrn5/firmware.c
+++ b/drivers/nfc/s3fwrn5/firmware.c
@@ -266,7 +266,7 @@ static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info)
 }
 
 /*
- * Firmware header stucture:
+ * Firmware header structure:
  *
  * 0x00 - 0x0B : Date and time string (w/o NUL termination)
  * 0x10 - 0x13 : Firmware version
-- 
2.17.1


^ permalink raw reply related	[relevance 99%]

* [PATCH net-next v2 3/3] nfc: s3fwrn5: Change the error code
       [not found]     <CGME20201117081137epcms2p84b5dd8d84ca608f44b0bb722b48f50b1@epcms2p8>
@ 2020-11-17  8:11 98% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17  8:11 UTC (permalink / raw)
  To: krzk, Krzysztof Opasiak; +Cc: linux-nfc, netdev, linux-kernel

ENOTSUPP is not a SUSV4 error code, prefer EOPNOTSUPP.

Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/s3fwrn5.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/s3fwrn5.h b/drivers/nfc/s3fwrn5/s3fwrn5.h
index 9d5f34759225..bb8f936d13a2 100644
--- a/drivers/nfc/s3fwrn5/s3fwrn5.h
+++ b/drivers/nfc/s3fwrn5/s3fwrn5.h
@@ -44,7 +44,7 @@ static inline int s3fwrn5_set_mode(struct s3fwrn5_info *info,
 	enum s3fwrn5_mode mode)
 {
 	if (!info->phy_ops->set_mode)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	info->phy_ops->set_mode(info->phy_id, mode);
 
@@ -54,7 +54,7 @@ static inline int s3fwrn5_set_mode(struct s3fwrn5_info *info,
 static inline enum s3fwrn5_mode s3fwrn5_get_mode(struct s3fwrn5_info *info)
 {
 	if (!info->phy_ops->get_mode)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return info->phy_ops->get_mode(info->phy_id);
 }
@@ -62,7 +62,7 @@ static inline enum s3fwrn5_mode s3fwrn5_get_mode(struct s3fwrn5_info *info)
 static inline int s3fwrn5_set_wake(struct s3fwrn5_info *info, bool wake)
 {
 	if (!info->phy_ops->set_wake)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	info->phy_ops->set_wake(info->phy_id, wake);
 
@@ -72,7 +72,7 @@ static inline int s3fwrn5_set_wake(struct s3fwrn5_info *info, bool wake)
 static inline int s3fwrn5_write(struct s3fwrn5_info *info, struct sk_buff *skb)
 {
 	if (!info->phy_ops->write)
-		return -ENOTSUPP;
+		return -EOPNOTSUPP;
 
 	return info->phy_ops->write(info->phy_id, skb);
 }
-- 
2.17.1


^ permalink raw reply related	[relevance 98%]

* Re: [PATCH net-next v2 1/3] nfc: s3fwrn5: Remove the max_payload
  @ 2020-11-17  8:14 78%     ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-17  8:14 UTC (permalink / raw)
  To: krzk; +Cc: Bongsu Jeon, Krzysztof Opasiak, linux-nfc, netdev, linux-kernel

2020-11-17 16:42 GMT+09:00, krzk@kernel.org <krzk@kernel.org>:
> On Tue, Nov 17, 2020 at 10:16:11AM +0900, Bongsu Jeon wrote:
>> max_payload is unused.
>
> Why did you resend the patch ignoring my review? I already provided you
> with a tag, so you should include it.
>
> https://www.kernel.org/doc/html/latest/process/submitting-patches.html
>
> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Best regards,
> Krzysztof
>

Sorry about that. I included the tag.

^ permalink raw reply	[relevance 78%]

* Re: [PATCH net-next v2 1/3] nfc: s3fwrn5: Remove the max_payload
  @ 2020-11-17 12:52 78%         ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-17 12:52 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Bongsu Jeon, Krzysztof Opasiak, linux-nfc, netdev, linux-kernel

On Tue, Nov 17, 2020 at 5:39 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Tue, 17 Nov 2020 at 09:14, Bongsu Jeon <bs.jeon87@gmail.com> wrote:
> >
> > 2020-11-17 16:42 GMT+09:00, krzk@kernel.org <krzk@kernel.org>:
> > > On Tue, Nov 17, 2020 at 10:16:11AM +0900, Bongsu Jeon wrote:
> > >> max_payload is unused.
> > >
> > > Why did you resend the patch ignoring my review? I already provided you
> > > with a tag, so you should include it.
> > >
> > > https://www.kernel.org/doc/html/latest/process/submitting-patches.html
> > >
> > > Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
> > >
> > > Best regards,
> > > Krzysztof
> > >
> >
> > Sorry about that. I included the tag.
>
> You need to reduce the rate of sending new patches. You sent v1. Then
> you sent again v1, which I reviewed. Then you send v2 without my
> review. So I provided a review. Then you sent again a v2 with my
> reviewed tags. So there are two v1 patches and two v2. Since I
> provided you the review tags for v2, no need to send v2 again. It
> confuses.
>
> Best regards,
> Krzysztof

Sorry to confuse you.
I made a mistake because I thought that you asked me
 to resend the patches with the new version(v2).
I think you intended that I need to version the patches and
describe changes when I update the patches next time.

Thanks a lot for reviewing my patches.

^ permalink raw reply	[relevance 78%]

* Re: [PATCH net-next] net/nfc/nci: Support NCI 2.x initial sequence
  @ 2020-11-18  4:29 78%     ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-18  4:29 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: Bongsu Jeon, davem, netdev, linux-kernel

On 11/18/20, Jakub Kicinski <kuba@kernel.org> wrote:
> On Tue, 17 Nov 2020 14:37:59 +0900 Bongsu Jeon wrote:
>> implement the NCI 2.x initial sequence to support NCI 2.x NFCC.
>> Since NCI 2.0, CORE_RESET and CORE_INIT sequence have been changed.
>> If NFCEE supports NCI 2.x, then NCI 2.x initial sequence will work.
>>
>> In NCI 1.0, Initial sequence and payloads are as below:
>> (DH)                     (NFCC)
>>  |  -- CORE_RESET_CMD --> |
>>  |  <-- CORE_RESET_RSP -- |
>>  |  -- CORE_INIT_CMD -->  |
>>  |  <-- CORE_INIT_RSP --  |
>>  CORE_RESET_RSP payloads are Status, NCI version, Configuration Status.
>>  CORE_INIT_CMD payloads are empty.
>>  CORE_INIT_RSP payloads are Status, NFCC Features,
>>     Number of Supported RF Interfaces, Supported RF Interface,
>>     Max Logical Connections, Max Routing table Size,
>>     Max Control Packet Payload Size, Max Size for Large Parameters,
>>     Manufacturer ID, Manufacturer Specific Information.
>>
>> In NCI 2.0, Initial Sequence and Parameters are as below:
>> (DH)                     (NFCC)
>>  |  -- CORE_RESET_CMD --> |
>>  |  <-- CORE_RESET_RSP -- |
>>  |  <-- CORE_RESET_NTF -- |
>>  |  -- CORE_INIT_CMD -->  |
>>  |  <-- CORE_INIT_RSP --  |
>>  CORE_RESET_RSP payloads are Status.
>>  CORE_RESET_NTF payloads are Reset Trigger,
>>     Configuration Status, NCI Version, Manufacturer ID,
>>     Manufacturer Specific Information Length,
>>     Manufacturer Specific Information.
>>  CORE_INIT_CMD payloads are Feature1, Feature2.
>>  CORE_INIT_RSP payloads are Status, NFCC Features,
>>     Max Logical Connections, Max Routing Table Size,
>>     Max Control Packet Payload Size,
>>     Max Data Packet Payload Size of the Static HCI Connection,
>>     Number of Credits of the Static HCI Connection,
>>     Max NFC-V RF Frame Size, Number of Supported RF Interfaces,
>>     Supported RF Interfaces.
>>
>> Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
>
> Please fix the following sparse (build with C=1) warning:
>
> net/nfc/nci/ntf.c:42:17: warning: cast to restricted __le32
>
>> +	__u8 status = 0;
>
> Please don't use the __u types in the normal kernel code, those are
> types for user space ABI.
>

Thanks for reviewing my patch.
I will change the code to fix it
and then resend my patch with version2.

^ permalink raw reply	[relevance 78%]

* [PATCH net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
       [not found]     <CGME20201123075526epcms2p59410a8ba942f8942f53a593d9df764d0@epcms2p5>
@ 2020-11-23  7:55 99% ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-23  7:55 UTC (permalink / raw)
  To: krzk, kuba; +Cc: linux-nfc, netdev, devicetree, linux-kernel

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 .../bindings/net/nfc/samsung,s3fwrn5.yaml     | 28 +++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
index cb0b8a560282..37b3e5ae5681 100644
--- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
@@ -13,6 +13,7 @@ maintainers:
 properties:
   compatible:
     const: samsung,s3fwrn5-i2c
+    const: samsung,s3fwrn82-uart
 
   en-gpios:
     maxItems: 1
@@ -47,10 +48,19 @@ additionalProperties: false
 required:
   - compatible
   - en-gpios
-  - interrupts
-  - reg
   - wake-gpios
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s3fwrn5-i2c
+    then:
+      required:
+        - interrupts
+        - reg
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
@@ -71,3 +81,17 @@ examples:
             wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
         };
     };
+  # UART example on Raspberry Pi
+  - |
+    &uart0 {
+        status = "okay";
+
+        s3fwrn82_uart {
+            compatible = "samsung,s3fwrn82-uart";
+
+            en-gpios = <&gpio 20 0>;
+            wake-gpios = <&gpio 16 0>;
+
+            status = "okay";
+        };
+    };
-- 
2.17.1


^ permalink raw reply related	[relevance 99%]

* [PATCH net-next 2/2] net: nfc: s3fwrn5: Support a UART interface
       [not found]     <CGME20201123075658epcms2p5a6237314f7a72a2556545d3f96261c93@epcms2p5>
@ 2020-11-23  7:56 78% ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-23  7:56 UTC (permalink / raw)
  To: krzk, kuba; +Cc: linux-kernel, linux-nfc, netdev

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 uses NCI protocol and supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/Kconfig  |  12 ++
 drivers/nfc/s3fwrn5/Makefile |   2 +
 drivers/nfc/s3fwrn5/uart.c   | 250 +++++++++++++++++++++++++++++++++++
 3 files changed, 264 insertions(+)
 create mode 100644 drivers/nfc/s3fwrn5/uart.c

diff --git a/drivers/nfc/s3fwrn5/Kconfig b/drivers/nfc/s3fwrn5/Kconfig
index 3f8b6da58280..6f88737769e1 100644
--- a/drivers/nfc/s3fwrn5/Kconfig
+++ b/drivers/nfc/s3fwrn5/Kconfig
@@ -20,3 +20,15 @@ config NFC_S3FWRN5_I2C
 	  To compile this driver as a module, choose m here. The module will
 	  be called s3fwrn5_i2c.ko.
 	  Say N if unsure.
+
+config NFC_S3FWRN82_UART
+	tristate "Samsung S3FWRN82 UART support"
+	depends on NFC_NCI && SERIAL_DEV_BUS
+	select NFC_S3FWRN5
+	help
+	  This module adds support for a UART interface to the S3FWRN82 chip.
+	  Select this if your platform is using the UART bus.
+
+	  To compile this driver as a module, choose m here. The module will
+	  be called s3fwrn82_uart.ko.
+	  Say N if unsure.
diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index d0ffa35f50e8..d1902102060b 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -5,6 +5,8 @@
 
 s3fwrn5-objs = core.o firmware.o nci.o
 s3fwrn5_i2c-objs = i2c.o
+s3fwrn82_uart-objs = uart.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
 obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
+obj-$(CONFIG_NFC_S3FWRN82_UART) += s3fwrn82_uart.o
diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
new file mode 100644
index 000000000000..b3c36a5b28d3
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/uart.c
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UART Link Layer for S3FWRN82 NCI based Driver
+ *
+ * Copyright (C) 2020 Samsung Electronics
+ * Author: Bongsu Jeon <bongsu.jeon@samsung.com>
+ * All rights reserved.
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/serdev.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include "s3fwrn5.h"
+
+#define S3FWRN82_UART_DRIVER_NAME "s3fwrn82_uart"
+#define S3FWRN82_NCI_HEADER 3
+#define S3FWRN82_NCI_IDX 2
+#define S3FWRN82_EN_WAIT_TIME 20
+#define NCI_SKB_BUFF_LEN 258
+
+struct s3fwrn82_uart_phy {
+	struct serdev_device *ser_dev;
+	struct nci_dev *ndev;
+	struct sk_buff *recv_skb;
+
+	unsigned int gpio_en;
+	unsigned int gpio_fw_wake;
+
+	/* mutex is used to synchronize */
+	struct mutex mutex;
+	enum s3fwrn5_mode mode;
+};
+
+static void s3fwrn82_uart_set_wake(void *phy_id, bool wake)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+	gpio_set_value(phy->gpio_fw_wake, wake);
+	msleep(S3FWRN82_EN_WAIT_TIME);
+	mutex_unlock(&phy->mutex);
+}
+
+static void s3fwrn82_uart_set_mode(void *phy_id, enum s3fwrn5_mode mode)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+	if (phy->mode == mode)
+		goto out;
+	phy->mode = mode;
+	gpio_set_value(phy->gpio_en, 1);
+	gpio_set_value(phy->gpio_fw_wake, 0);
+	if (mode == S3FWRN5_MODE_FW)
+		gpio_set_value(phy->gpio_fw_wake, 1);
+	if (mode != S3FWRN5_MODE_COLD) {
+		msleep(S3FWRN82_EN_WAIT_TIME);
+		gpio_set_value(phy->gpio_en, 0);
+		msleep(S3FWRN82_EN_WAIT_TIME);
+	}
+out:
+	mutex_unlock(&phy->mutex);
+}
+
+static enum s3fwrn5_mode s3fwrn82_uart_get_mode(void *phy_id)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+	enum s3fwrn5_mode mode;
+
+	mutex_lock(&phy->mutex);
+	mode = phy->mode;
+	mutex_unlock(&phy->mutex);
+	return mode;
+}
+
+static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+	int err;
+
+	err = serdev_device_write(phy->ser_dev,
+				  out->data, out->len,
+				  MAX_SCHEDULE_TIMEOUT);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static const struct s3fwrn5_phy_ops uart_phy_ops = {
+	.set_wake = s3fwrn82_uart_set_wake,
+	.set_mode = s3fwrn82_uart_set_mode,
+	.get_mode = s3fwrn82_uart_get_mode,
+	.write = s3fwrn82_uart_write,
+};
+
+static int s3fwrn82_uart_read(struct serdev_device *serdev,
+			      const unsigned char *data,
+			      size_t count)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	size_t i;
+
+	for (i = 0; i < count; i++) {
+		skb_put_u8(phy->recv_skb, *data++);
+
+		if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
+			continue;
+
+		if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
+				< phy->recv_skb->data[S3FWRN82_NCI_IDX])
+			continue;
+
+		s3fwrn5_recv_frame(phy->ndev, phy->recv_skb, phy->mode);
+		phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+		if (!phy->recv_skb)
+			return 0;
+	}
+
+	return i;
+}
+
+static struct serdev_device_ops s3fwrn82_serdev_ops = {
+	.receive_buf = s3fwrn82_uart_read,
+	.write_wakeup = serdev_device_write_wakeup,
+};
+
+static const struct of_device_id s3fwrn82_uart_of_match[] = {
+	{ .compatible = "samsung,s3fwrn82-uart", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
+
+static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	struct device_node *np = serdev->dev.of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->gpio_en))
+		return -ENODEV;
+
+	phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->gpio_fw_wake))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int s3fwrn82_uart_probe(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy;
+	int ret = -ENOMEM;
+
+	phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		goto err_exit;
+
+	phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+	if (!phy->recv_skb)
+		goto err_free;
+
+	mutex_init(&phy->mutex);
+	phy->mode = S3FWRN5_MODE_COLD;
+
+	phy->ser_dev = serdev;
+	serdev_device_set_drvdata(serdev, phy);
+	serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
+	ret = serdev_device_open(serdev);
+	if (ret) {
+		dev_err(&serdev->dev, "Unable to open device\n");
+		goto err_skb;
+	}
+
+	ret = serdev_device_set_baudrate(serdev, 115200);
+	if (ret != 115200) {
+		ret = -EINVAL;
+		goto err_serdev;
+	}
+
+	serdev_device_set_flow_control(serdev, false);
+
+	ret = s3fwrn82_uart_parse_dt(serdev);
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev,
+				    phy->gpio_en,
+				    GPIOF_OUT_INIT_HIGH,
+				    "s3fwrn82_en");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev,
+				    phy->gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW,
+				    "s3fwrn82_fw_wake");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->ser_dev->dev, &uart_phy_ops);
+	if (ret < 0)
+		goto err_serdev;
+
+	return ret;
+
+err_serdev:
+	serdev_device_close(serdev);
+err_skb:
+	kfree_skb(phy->recv_skb);
+err_free:
+	kfree(phy);
+err_exit:
+	return ret;
+}
+
+static void s3fwrn82_uart_remove(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+
+	s3fwrn5_remove(phy->ndev);
+	serdev_device_close(serdev);
+	kfree_skb(phy->recv_skb);
+	kfree(phy);
+}
+
+static struct serdev_device_driver s3fwrn82_uart_driver = {
+	.probe = s3fwrn82_uart_probe,
+	.remove = s3fwrn82_uart_remove,
+	.driver = {
+		.name = S3FWRN82_UART_DRIVER_NAME,
+		.of_match_table = of_match_ptr(s3fwrn82_uart_of_match),
+	},
+};
+
+module_serdev_device_driver(s3fwrn82_uart_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UART driver for Samsung NFC");
+MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
-- 
2.17.1


^ permalink raw reply related	[relevance 78%]

* [PATCH net-next v2] net/nfc/nci: Support NCI 2.x initial sequence
       [not found]     <CGME20201123101208epcms2p71d4c8d66f08fb7a2e10ae422abde3389@epcms2p7>
@ 2020-11-23 10:12 74% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-23 10:12 UTC (permalink / raw)
  To: davem, kuba; +Cc: netdev, linux-kernel

implement the NCI 2.x initial sequence to support NCI 2.x NFCC.
Since NCI 2.0, CORE_RESET and CORE_INIT sequence have been changed.
If NFCEE supports NCI 2.x, then NCI 2.x initial sequence will work.

In NCI 1.0, Initial sequence and payloads are as below:
(DH)                     (NFCC)
 |  -- CORE_RESET_CMD --> |
 |  <-- CORE_RESET_RSP -- |
 |  -- CORE_INIT_CMD -->  |
 |  <-- CORE_INIT_RSP --  |
 CORE_RESET_RSP payloads are Status, NCI version, Configuration Status.
 CORE_INIT_CMD payloads are empty.
 CORE_INIT_RSP payloads are Status, NFCC Features,
    Number of Supported RF Interfaces, Supported RF Interface,
    Max Logical Connections, Max Routing table Size,
    Max Control Packet Payload Size, Max Size for Large Parameters,
    Manufacturer ID, Manufacturer Specific Information.

In NCI 2.0, Initial Sequence and Parameters are as below:
(DH)                     (NFCC)
 |  -- CORE_RESET_CMD --> |
 |  <-- CORE_RESET_RSP -- |
 |  <-- CORE_RESET_NTF -- |
 |  -- CORE_INIT_CMD -->  |
 |  <-- CORE_INIT_RSP --  |
 CORE_RESET_RSP payloads are Status.
 CORE_RESET_NTF payloads are Reset Trigger,
    Configuration Status, NCI Version, Manufacturer ID,
    Manufacturer Specific Information Length,
    Manufacturer Specific Information.
 CORE_INIT_CMD payloads are Feature1, Feature2.
 CORE_INIT_RSP payloads are Status, NFCC Features,
    Max Logical Connections, Max Routing Table Size,
    Max Control Packet Payload Size,
    Max Data Packet Payload Size of the Static HCI Connection,
    Number of Credits of the Static HCI Connection,
    Max NFC-V RF Frame Size, Number of Supported RF Interfaces,
    Supported RF Interfaces.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 Changes in v2:
  - fix the warning of type casting.
  - changed the __u8 type to unsigned char.

 include/net/nfc/nci.h | 39 ++++++++++++++++++++++
 net/nfc/nci/core.c    | 23 +++++++++++--
 net/nfc/nci/ntf.c     | 21 ++++++++++++
 net/nfc/nci/rsp.c     | 75 +++++++++++++++++++++++++++++++++++++------
 4 files changed, 146 insertions(+), 12 deletions(-)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index 0550e0380b8d..decc89803d4b 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -25,6 +25,8 @@
 #define NCI_MAX_PARAM_LEN					251
 #define NCI_MAX_PAYLOAD_SIZE					255
 #define NCI_MAX_PACKET_SIZE					258
+#define NCI_MAX_LARGE_PARAMS_NCI_v2				15
+#define NCI_VER_2_MASK						0x20
 
 /* NCI Status Codes */
 #define NCI_STATUS_OK						0x00
@@ -131,6 +133,9 @@
 #define NCI_LF_CON_BITR_F_212					0x02
 #define NCI_LF_CON_BITR_F_424					0x04
 
+/* NCI 2.x Feature Enable Bit */
+#define NCI_FEATURE_DISABLE					0x00
+
 /* NCI Reset types */
 #define NCI_RESET_TYPE_KEEP_CONFIG				0x00
 #define NCI_RESET_TYPE_RESET_CONFIG				0x01
@@ -220,6 +225,11 @@ struct nci_core_reset_cmd {
 } __packed;
 
 #define NCI_OP_CORE_INIT_CMD		nci_opcode_pack(NCI_GID_CORE, 0x01)
+/* To support NCI 2.x */
+struct nci_core_init_v2_cmd {
+	unsigned char	feature1;
+	unsigned char	feature2;
+} __packed;
 
 #define NCI_OP_CORE_SET_CONFIG_CMD	nci_opcode_pack(NCI_GID_CORE, 0x02)
 struct set_config_param {
@@ -316,6 +326,11 @@ struct nci_core_reset_rsp {
 	__u8	config_status;
 } __packed;
 
+/* To support NCI ver 2.x */
+struct nci_core_reset_rsp_nci_ver2 {
+	unsigned char	status;
+} __packed;
+
 #define NCI_OP_CORE_INIT_RSP		nci_opcode_pack(NCI_GID_CORE, 0x01)
 struct nci_core_init_rsp_1 {
 	__u8	status;
@@ -334,6 +349,20 @@ struct nci_core_init_rsp_2 {
 	__le32	manufact_specific_info;
 } __packed;
 
+/* To support NCI ver 2.x */
+struct nci_core_init_rsp_nci_ver2 {
+	unsigned char	status;
+	__le32	nfcc_features;
+	unsigned char	max_logical_connections;
+	__le16	max_routing_table_size;
+	unsigned char	max_ctrl_pkt_payload_len;
+	unsigned char	max_data_pkt_hci_payload_len;
+	unsigned char	number_of_hci_credit;
+	__le16	max_nfc_v_frame_size;
+	unsigned char	num_supported_rf_interfaces;
+	unsigned char	supported_rf_interfaces[];
+} __packed;
+
 #define NCI_OP_CORE_SET_CONFIG_RSP	nci_opcode_pack(NCI_GID_CORE, 0x02)
 struct nci_core_set_config_rsp {
 	__u8	status;
@@ -372,6 +401,16 @@ struct nci_nfcee_discover_rsp {
 /* --------------------------- */
 /* ---- NCI Notifications ---- */
 /* --------------------------- */
+#define NCI_OP_CORE_RESET_NTF		nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_ntf {
+	unsigned char	reset_trigger;
+	unsigned char	config_status;
+	unsigned char	nci_ver;
+	unsigned char	manufact_id;
+	unsigned char	manufacturer_specific_len;
+	__le32	manufact_specific_info;
+} __packed;
+
 #define NCI_OP_CORE_CONN_CREDITS_NTF	nci_opcode_pack(NCI_GID_CORE, 0x06)
 struct conn_credit_entry {
 	__u8	conn_id;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 4953ee5146e1..68889faadda2 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -165,7 +165,14 @@ static void nci_reset_req(struct nci_dev *ndev, unsigned long opt)
 
 static void nci_init_req(struct nci_dev *ndev, unsigned long opt)
 {
-	nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+	struct nci_core_init_v2_cmd *cmd = (struct nci_core_init_v2_cmd *)opt;
+
+	if (!cmd) {
+		nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+	} else {
+		/* if nci version is 2.0, then use the feature parameters */
+		nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, sizeof(struct nci_core_init_v2_cmd), cmd);
+	}
 }
 
 static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
@@ -497,8 +504,18 @@ static int nci_open_device(struct nci_dev *ndev)
 	}
 
 	if (!rc) {
-		rc = __nci_request(ndev, nci_init_req, 0,
-				   msecs_to_jiffies(NCI_INIT_TIMEOUT));
+		if (!(ndev->nci_ver & NCI_VER_2_MASK)) {
+			rc = __nci_request(ndev, nci_init_req, 0,
+					   msecs_to_jiffies(NCI_INIT_TIMEOUT));
+		} else {
+			struct nci_core_init_v2_cmd nci_init_v2_cmd;
+
+			nci_init_v2_cmd.feature1 = NCI_FEATURE_DISABLE;
+			nci_init_v2_cmd.feature2 = NCI_FEATURE_DISABLE;
+
+			rc = __nci_request(ndev, nci_init_req, (unsigned long)&nci_init_v2_cmd,
+					   msecs_to_jiffies(NCI_INIT_TIMEOUT));
+		}
 	}
 
 	if (!rc && ndev->ops->post_setup)
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 33e1170817f0..98af04c86b2c 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -27,6 +27,23 @@
 
 /* Handle NCI Notification packets */
 
+static void nci_core_reset_ntf_packet(struct nci_dev *ndev,
+				      struct sk_buff *skb)
+{
+	/* Handle NCI 2.x core reset notification */
+	struct nci_core_reset_ntf *ntf = (void *)skb->data;
+
+	ndev->nci_ver = ntf->nci_ver;
+	pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+		 ntf->nci_ver, ntf->config_status);
+
+	ndev->manufact_id = ntf->manufact_id;
+	ndev->manufact_specific_info =
+		__le32_to_cpu(ntf->manufact_specific_info);
+
+	nci_req_complete(ndev, NCI_STATUS_OK);
+}
+
 static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
 					     struct sk_buff *skb)
 {
@@ -756,6 +773,10 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	}
 
 	switch (ntf_opcode) {
+	case NCI_OP_CORE_RESET_NTF:
+		nci_core_reset_ntf_packet(ndev, skb);
+		break;
+
 	case NCI_OP_CORE_CONN_CREDITS_NTF:
 		nci_core_conn_credits_ntf_packet(ndev, skb);
 		break;
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index a48297b79f34..521fa0383d48 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -31,16 +31,19 @@ static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 
 	pr_debug("status 0x%x\n", rsp->status);
 
-	if (rsp->status == NCI_STATUS_OK) {
-		ndev->nci_ver = rsp->nci_ver;
-		pr_debug("nci_ver 0x%x, config_status 0x%x\n",
-			 rsp->nci_ver, rsp->config_status);
-	}
+	/* Handle NCI 1.x ver */
+	if (skb->len != 1) {
+		if (rsp->status == NCI_STATUS_OK) {
+			ndev->nci_ver = rsp->nci_ver;
+			pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+				 rsp->nci_ver, rsp->config_status);
+		}
 
-	nci_req_complete(ndev, rsp->status);
+		nci_req_complete(ndev, rsp->status);
+	}
 }
 
-static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+static unsigned char nci_core_init_rsp_packet_v1(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
 	struct nci_core_init_rsp_2 *rsp_2;
@@ -48,7 +51,7 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	pr_debug("status 0x%x\n", rsp_1->status);
 
 	if (rsp_1->status != NCI_STATUS_OK)
-		goto exit;
+		return rsp_1->status;
 
 	ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
 	ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
@@ -77,6 +80,60 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	ndev->manufact_specific_info =
 		__le32_to_cpu(rsp_2->manufact_specific_info);
 
+	return NCI_STATUS_OK;
+}
+
+static unsigned char nci_core_init_rsp_packet_v2(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
+	unsigned char rf_interface_idx = 0;
+	unsigned char rf_extension_cnt = 0;
+	unsigned char *supported_rf_interface = rsp->supported_rf_interfaces;
+
+	pr_debug("status %x\n", rsp->status);
+
+	if (rsp->status != NCI_STATUS_OK)
+		return rsp->status;
+
+	ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
+	ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
+
+	if (ndev->num_supported_rf_interfaces >
+	    NCI_MAX_SUPPORTED_RF_INTERFACES) {
+		ndev->num_supported_rf_interfaces =
+			NCI_MAX_SUPPORTED_RF_INTERFACES;
+	}
+
+	while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
+		ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
+
+		/* skip rf extension parameters */
+		rf_extension_cnt = *supported_rf_interface++;
+		supported_rf_interface += rf_extension_cnt;
+	}
+
+	ndev->max_logical_connections = rsp->max_logical_connections;
+	ndev->max_routing_table_size =
+			__le16_to_cpu(rsp->max_routing_table_size);
+	ndev->max_ctrl_pkt_payload_len =
+			rsp->max_ctrl_pkt_payload_len;
+	ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2;
+
+	return NCI_STATUS_OK;
+}
+
+static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	unsigned char status = 0;
+
+	if (!(ndev->nci_ver & NCI_VER_2_MASK))
+		status = nci_core_init_rsp_packet_v1(ndev, skb);
+	else
+		status = nci_core_init_rsp_packet_v2(ndev, skb);
+
+	if (status != NCI_STATUS_OK)
+		goto exit;
+
 	pr_debug("nfcc_features 0x%x\n",
 		 ndev->nfcc_features);
 	pr_debug("num_supported_rf_interfaces %d\n",
@@ -103,7 +160,7 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		 ndev->manufact_specific_info);
 
 exit:
-	nci_req_complete(ndev, rsp_1->status);
+	nci_req_complete(ndev, status);
 }
 
 static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
-- 
2.17.1


^ permalink raw reply related	[relevance 74%]

* Re: [PATCH net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  @ 2020-11-24 11:39 90%     ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-24 11:39 UTC (permalink / raw)
  To: krzk; +Cc: Bongsu Jeon, kuba, linux-nfc, netdev, devicetree, linux-kernel

On Mon, Nov 23, 2020 at 5:02 PM krzk@kernel.org <krzk@kernel.org> wrote:
>
> On Mon, Nov 23, 2020 at 04:55:26PM +0900, Bongsu Jeon wrote:
> > Since S3FWRN82 NFC Chip, The UART interface can be used.
> > S3FWRN82 supports I2C and UART interface.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> > ---
> >  .../bindings/net/nfc/samsung,s3fwrn5.yaml     | 28 +++++++++++++++++--
> >  1 file changed, 26 insertions(+), 2 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
> > index cb0b8a560282..37b3e5ae5681 100644
> > --- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
> > +++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
> > @@ -13,6 +13,7 @@ maintainers:
> >  properties:
> >    compatible:
> >      const: samsung,s3fwrn5-i2c
> > +    const: samsung,s3fwrn82-uart
>
> This does not work, you need to use enum. Did you run at least
> dt_bindings_check?
>
Sorry. I didn't. I fixed it as below and ran dt_bindings_check.
    compatible:
       oneOf:
           - enum:
               - samsung,s3fwrn5-i2c
               - samsung,s3fwrn82


> The compatible should be just "samsung,s3fwrn82". I think it was a
> mistake in the first s3fwrn5 submission to add a interface to
> compatible.
>
Ok. I will change the name.

> >
> >    en-gpios:
> >      maxItems: 1
> > @@ -47,10 +48,19 @@ additionalProperties: false
> >  required:
> >    - compatible
> >    - en-gpios
> > -  - interrupts
> > -  - reg
> >    - wake-gpios
> >
> > +allOf:
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            const: samsung,s3fwrn5-i2c
> > +    then:
> > +      required:
> > +        - interrupts
> > +        - reg
> > +
> >  examples:
> >    - |
> >      #include <dt-bindings/gpio/gpio.h>
> > @@ -71,3 +81,17 @@ examples:
> >              wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
> >          };
> >      };
> > +  # UART example on Raspberry Pi
> > +  - |
> > +    &uart0 {
> > +        status = "okay";
> > +
> > +        s3fwrn82_uart {
>
> Just "bluetooth" to follow Devicetree specification.
Sorry. I don't understand this comment.
Could you explain it?
Does it mean i need to refer to the net/broadcom-bluetooth.txt?

>
> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next 2/2] net: nfc: s3fwrn5: Support a UART interface
  @ 2020-11-24 12:05 89%     ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-24 12:05 UTC (permalink / raw)
  To: krzk; +Cc: Bongsu Jeon, kuba, linux-kernel, linux-nfc, netdev

On Mon, Nov 23, 2020 at 5:55 PM krzk@kernel.org <krzk@kernel.org> wrote:
>
> On Mon, Nov 23, 2020 at 04:56:58PM +0900, Bongsu Jeon wrote:
> > Since S3FWRN82 NFC Chip, The UART interface can be used.
> > S3FWRN82 uses NCI protocol and supports I2C and UART interface.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
>
> Please start sending emails properly, e.g. with git send-email, so all
> your patches in the patchset are referencing the first patch.
>
Ok. I will do that.

> > ---
> >  drivers/nfc/s3fwrn5/Kconfig  |  12 ++
> >  drivers/nfc/s3fwrn5/Makefile |   2 +
> >  drivers/nfc/s3fwrn5/uart.c   | 250 +++++++++++++++++++++++++++++++++++
> >  3 files changed, 264 insertions(+)
> >  create mode 100644 drivers/nfc/s3fwrn5/uart.c
> >
> > diff --git a/drivers/nfc/s3fwrn5/Kconfig b/drivers/nfc/s3fwrn5/Kconfig
> > index 3f8b6da58280..6f88737769e1 100644
> > --- a/drivers/nfc/s3fwrn5/Kconfig
> > +++ b/drivers/nfc/s3fwrn5/Kconfig
> > @@ -20,3 +20,15 @@ config NFC_S3FWRN5_I2C
> >         To compile this driver as a module, choose m here. The module will
> >         be called s3fwrn5_i2c.ko.
> >         Say N if unsure.
> > +
> > +config NFC_S3FWRN82_UART
> > +     tristate "Samsung S3FWRN82 UART support"
> > +     depends on NFC_NCI && SERIAL_DEV_BUS
>
> What about SERIAL_DEV_BUS as module? Shouldn't this be
> SERIAL_DEV_BUS || !SERIAL_DEV_BUS?
>

SERIAL_DEV_BUS is okay even if SERIAL_DEV_BUS is defined as module.

> > +     select NFC_S3FWRN5
> > +     help
> > +       This module adds support for a UART interface to the S3FWRN82 chip.
> > +       Select this if your platform is using the UART bus.
> > +
> > +       To compile this driver as a module, choose m here. The module will
> > +       be called s3fwrn82_uart.ko.
> > +       Say N if unsure.
> > diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
> > index d0ffa35f50e8..d1902102060b 100644
> > --- a/drivers/nfc/s3fwrn5/Makefile
> > +++ b/drivers/nfc/s3fwrn5/Makefile
> > @@ -5,6 +5,8 @@
> >
> >  s3fwrn5-objs = core.o firmware.o nci.o
> >  s3fwrn5_i2c-objs = i2c.o
> > +s3fwrn82_uart-objs = uart.o
> >
> >  obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
> >  obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
> > +obj-$(CONFIG_NFC_S3FWRN82_UART) += s3fwrn82_uart.o
> > diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
> > new file mode 100644
> > index 000000000000..b3c36a5b28d3
> > --- /dev/null
> > +++ b/drivers/nfc/s3fwrn5/uart.c
> > @@ -0,0 +1,250 @@
> > +// SPDX-License-Identifier: GPL-2.0+
> > +/*
> > + * UART Link Layer for S3FWRN82 NCI based Driver
> > + *
> > + * Copyright (C) 2020 Samsung Electronics
> > + * Author: Bongsu Jeon <bongsu.jeon@samsung.com>
>
> You copied a lot from existing i2c.c. Please keep also the original
> copyrights.
>

Okay. I will keep also the original copyrights.

> > + * All rights reserved.
> > + */
> > +
> > +#include <linux/device.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/nfc.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/of.h>
> > +#include <linux/serdev.h>
> > +#include <linux/gpio.h>
> > +#include <linux/of_gpio.h>
> > +
> > +#include "s3fwrn5.h"
> > +
> > +#define S3FWRN82_UART_DRIVER_NAME "s3fwrn82_uart"
>
> Remove the define, it is used only once.
>
> > +#define S3FWRN82_NCI_HEADER 3
> > +#define S3FWRN82_NCI_IDX 2
> > +#define S3FWRN82_EN_WAIT_TIME 20
> > +#define NCI_SKB_BUFF_LEN 258
> > +
> > +struct s3fwrn82_uart_phy {
> > +     struct serdev_device *ser_dev;
> > +     struct nci_dev *ndev;
> > +     struct sk_buff *recv_skb;
> > +
> > +     unsigned int gpio_en;
> > +     unsigned int gpio_fw_wake;
> > +
> > +     /* mutex is used to synchronize */
>
> Please do not write obvious comments. Mutex is always used to
> synchronize, what else is it for? Instead you must describe what exactly
> is protected with mutex.
>

I understand it. I will fix it.

> > +     struct mutex mutex;
> > +     enum s3fwrn5_mode mode;
> > +};
> > +
> > +static void s3fwrn82_uart_set_wake(void *phy_id, bool wake)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = phy_id;
> > +
> > +     mutex_lock(&phy->mutex);
> > +     gpio_set_value(phy->gpio_fw_wake, wake);
> > +     msleep(S3FWRN82_EN_WAIT_TIME);
> > +     mutex_unlock(&phy->mutex);
> > +}
> > +
> > +static void s3fwrn82_uart_set_mode(void *phy_id, enum s3fwrn5_mode mode)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = phy_id;
> > +
> > +     mutex_lock(&phy->mutex);
> > +     if (phy->mode == mode)
> > +             goto out;
> > +     phy->mode = mode;
> > +     gpio_set_value(phy->gpio_en, 1);
> > +     gpio_set_value(phy->gpio_fw_wake, 0);
> > +     if (mode == S3FWRN5_MODE_FW)
> > +             gpio_set_value(phy->gpio_fw_wake, 1);
> > +     if (mode != S3FWRN5_MODE_COLD) {
> > +             msleep(S3FWRN82_EN_WAIT_TIME);
> > +             gpio_set_value(phy->gpio_en, 0);
> > +             msleep(S3FWRN82_EN_WAIT_TIME);
> > +     }
> > +out:
> > +     mutex_unlock(&phy->mutex);
> > +}
> > +
> > +static enum s3fwrn5_mode s3fwrn82_uart_get_mode(void *phy_id)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = phy_id;
> > +     enum s3fwrn5_mode mode;
> > +
> > +     mutex_lock(&phy->mutex);
> > +     mode = phy->mode;
> > +     mutex_unlock(&phy->mutex);
> > +     return mode;
> > +}
>
> All this duplicates I2C version. You need to start either reusing common
> blocks.
>

Okay. I will do refactoring on i2c.c and uart.c to make common blocks.
 is it okay to separate a patch for it?

> > +
> > +static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = phy_id;
> > +     int err;
> > +
> > +     err = serdev_device_write(phy->ser_dev,
> > +                               out->data, out->len,
> > +                               MAX_SCHEDULE_TIMEOUT);
> > +     if (err < 0)
> > +             return err;
> > +
> > +     return 0;
> > +}
> > +
> > +static const struct s3fwrn5_phy_ops uart_phy_ops = {
> > +     .set_wake = s3fwrn82_uart_set_wake,
> > +     .set_mode = s3fwrn82_uart_set_mode,
> > +     .get_mode = s3fwrn82_uart_get_mode,
> > +     .write = s3fwrn82_uart_write,
> > +};
> > +
> > +static int s3fwrn82_uart_read(struct serdev_device *serdev,
> > +                           const unsigned char *data,
> > +                           size_t count)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
> > +     size_t i;
> > +
> > +     for (i = 0; i < count; i++) {
> > +             skb_put_u8(phy->recv_skb, *data++);
> > +
> > +             if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
> > +                     continue;
> > +
> > +             if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
> > +                             < phy->recv_skb->data[S3FWRN82_NCI_IDX])
> > +                     continue;
> > +
> > +             s3fwrn5_recv_frame(phy->ndev, phy->recv_skb, phy->mode);
> > +             phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
> > +             if (!phy->recv_skb)
> > +                     return 0;
> > +     }
> > +
> > +     return i;
> > +}
> > +
> > +static struct serdev_device_ops s3fwrn82_serdev_ops = {
>
> const
>
> > +     .receive_buf = s3fwrn82_uart_read,
> > +     .write_wakeup = serdev_device_write_wakeup,
> > +};
> > +
> > +static const struct of_device_id s3fwrn82_uart_of_match[] = {
> > +     { .compatible = "samsung,s3fwrn82-uart", },
> > +     {},
> > +};
> > +MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
> > +
> > +static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
> > +     struct device_node *np = serdev->dev.of_node;
> > +
> > +     if (!np)
> > +             return -ENODEV;
> > +
> > +     phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
> > +     if (!gpio_is_valid(phy->gpio_en))
> > +             return -ENODEV;
> > +
> > +     phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
>
> You should not cast it it unsigned int. I'll fix the s3fwrn5 from which
> you copied this apparently.
>

Okay. I will fix it.

> > +     if (!gpio_is_valid(phy->gpio_fw_wake))
> > +             return -ENODEV;
> > +
> > +     return 0;
> > +}
> > +
> > +static int s3fwrn82_uart_probe(struct serdev_device *serdev)
> > +{
> > +     struct s3fwrn82_uart_phy *phy;
> > +     int ret = -ENOMEM;
> > +
> > +     phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
> > +     if (!phy)
> > +             goto err_exit;
> > +
> > +     phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
> > +     if (!phy->recv_skb)
> > +             goto err_free;
> > +
> > +     mutex_init(&phy->mutex);
> > +     phy->mode = S3FWRN5_MODE_COLD;
> > +
> > +     phy->ser_dev = serdev;
> > +     serdev_device_set_drvdata(serdev, phy);
> > +     serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
> > +     ret = serdev_device_open(serdev);
> > +     if (ret) {
> > +             dev_err(&serdev->dev, "Unable to open device\n");
> > +             goto err_skb;
> > +     }
> > +
> > +     ret = serdev_device_set_baudrate(serdev, 115200);
>
> Why baudrate is fixed?
>

RN82 NFC chip only supports 115200 baudrate for UART.

> > +     if (ret != 115200) {
> > +             ret = -EINVAL;
> > +             goto err_serdev;
> > +     }
> > +
> > +     serdev_device_set_flow_control(serdev, false);
> > +
> > +     ret = s3fwrn82_uart_parse_dt(serdev);
> > +     if (ret < 0)
> > +             goto err_serdev;
> > +
> > +     ret = devm_gpio_request_one(&phy->ser_dev->dev,
> > +                                 phy->gpio_en,
> > +                                 GPIOF_OUT_INIT_HIGH,
> > +                                 "s3fwrn82_en");
>
> This is weirdly wrapped.
>

Did you ask about devem_gpio_request_one function's parenthesis and parameters?
If it is right, I changed it after i ran the checkpatch.pl --strict and
i saw message like the alignment should match open parenthesis.

> > +     if (ret < 0)
> > +             goto err_serdev;
> > +
> > +     ret = devm_gpio_request_one(&phy->ser_dev->dev,
> > +                                 phy->gpio_fw_wake,
> > +                                 GPIOF_OUT_INIT_LOW,
> > +                                 "s3fwrn82_fw_wake");
> > +     if (ret < 0)
> > +             goto err_serdev;
> > +
> > +     ret = s3fwrn5_probe(&phy->ndev, phy, &phy->ser_dev->dev, &uart_phy_ops);
> > +     if (ret < 0)
> > +             goto err_serdev;
> > +
> > +     return ret;
> > +
> > +err_serdev:
> > +     serdev_device_close(serdev);
> > +err_skb:
> > +     kfree_skb(phy->recv_skb);
> > +err_free:
> > +     kfree(phy);
>
> Eee.... why? Did you test this code?
>

I didn't test this code. i just added this code as defense code.
If the error happens, then allocated memory and device will be free
according to the fail case.

> > +err_exit:
> > +     return ret;
> > +}
> > +
> > +static void s3fwrn82_uart_remove(struct serdev_device *serdev)
> > +{
> > +     struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
> > +
> > +     s3fwrn5_remove(phy->ndev);
> > +     serdev_device_close(serdev);
> > +     kfree_skb(phy->recv_skb);
> > +     kfree(phy);
>
> This does not look like tested...
>

I tested this code using unbind of the serial device.
It worked and I saw the debugging log that i added for checking the
code to be sure.

> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 89%]

* Re: [PATCH net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  @ 2020-11-25  3:08 90%         ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-25  3:08 UTC (permalink / raw)
  To: krzk; +Cc: Bongsu Jeon, kuba, linux-nfc, netdev, devicetree, linux-kernel

On 11/24/20, krzk@kernel.org <krzk@kernel.org> wrote:
> On Tue, Nov 24, 2020 at 08:39:40PM +0900, Bongsu Jeon wrote:
>> On Mon, Nov 23, 2020 at 5:02 PM krzk@kernel.org <krzk@kernel.org> wrote:
>> >
>> > On Mon, Nov 23, 2020 at 04:55:26PM +0900, Bongsu Jeon wrote:
>  > >  examples:
>> > >    - |
>> > >      #include <dt-bindings/gpio/gpio.h>
>> > > @@ -71,3 +81,17 @@ examples:
>> > >              wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
>> > >          };
>> > >      };
>> > > +  # UART example on Raspberry Pi
>> > > +  - |
>> > > +    &uart0 {
>> > > +        status = "okay";
>> > > +
>> > > +        s3fwrn82_uart {
>> >
>> > Just "bluetooth" to follow Devicetree specification.
>> Sorry. I don't understand this comment.
>> Could you explain it?
>> Does it mean i need to refer to the net/broadcom-bluetooth.txt?
>
> The node name should be "bluetooth", not "s3fwrn82_uart", because of
> Devicetree naming convention - node names should represent generic class
> of a device.
>
Actually, RN82 is the nfc device.
So, is it okay to use the name as nfc instead of Bluetooth?

> Best regards,
> Krzysztof
>
>

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next 2/2] net: nfc: s3fwrn5: Support a UART interface
  @ 2020-11-25  4:01 90%         ` Bongsu Jeon
  2020-11-25  4:43 90%           ` Bongsu Jeon
  0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-25  4:01 UTC (permalink / raw)
  To: krzk; +Cc: Bongsu Jeon, kuba, linux-kernel, linux-nfc, netdev

On 11/24/20, krzk@kernel.org <krzk@kernel.org> wrote:
> On Tue, Nov 24, 2020 at 09:05:52PM +0900, Bongsu Jeon wrote:
>> On Mon, Nov 23, 2020 at 5:55 PM krzk@kernel.org <krzk@kernel.org> wrote:
>> > > +static enum s3fwrn5_mode s3fwrn82_uart_get_mode(void *phy_id)
>> > > +{
>> > > +     struct s3fwrn82_uart_phy *phy = phy_id;
>> > > +     enum s3fwrn5_mode mode;
>> > > +
>> > > +     mutex_lock(&phy->mutex);
>> > > +     mode = phy->mode;
>> > > +     mutex_unlock(&phy->mutex);
>> > > +     return mode;
>> > > +}
>> >
>> > All this duplicates I2C version. You need to start either reusing
>> > common
>> > blocks.
>> >
>>
>> Okay. I will do refactoring on i2c.c and uart.c to make common blocks.
>>  is it okay to separate a patch for it?
>
> Yes, that would be the best - refactor the driver to split some common
> methods and then in next patch add new s3fwrn82 UART driver.
>
>> > > +
>> > > +static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
>> > > +{
>> > > +     struct s3fwrn82_uart_phy *phy = phy_id;
>> > > +     int err;
>> > > +
>> > > +     err = serdev_device_write(phy->ser_dev,
>> > > +                               out->data, out->len,
>> > > +                               MAX_SCHEDULE_TIMEOUT);
>> > > +     if (err < 0)
>> > > +             return err;
>> > > +
>> > > +     return 0;
>> > > +}
>> > > +
>> > > +static const struct s3fwrn5_phy_ops uart_phy_ops = {
>> > > +     .set_wake = s3fwrn82_uart_set_wake,
>> > > +     .set_mode = s3fwrn82_uart_set_mode,
>> > > +     .get_mode = s3fwrn82_uart_get_mode,
>> > > +     .write = s3fwrn82_uart_write,
>> > > +};
>> > > +
>> > > +static int s3fwrn82_uart_read(struct serdev_device *serdev,
>> > > +                           const unsigned char *data,
>> > > +                           size_t count)
>> > > +{
>> > > +     struct s3fwrn82_uart_phy *phy =
>> > > serdev_device_get_drvdata(serdev);
>> > > +     size_t i;
>> > > +
>> > > +     for (i = 0; i < count; i++) {
>> > > +             skb_put_u8(phy->recv_skb, *data++);
>> > > +
>> > > +             if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
>> > > +                     continue;
>> > > +
>> > > +             if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
>> > > +                             <
>> > > phy->recv_skb->data[S3FWRN82_NCI_IDX])
>> > > +                     continue;
>> > > +
>> > > +             s3fwrn5_recv_frame(phy->ndev, phy->recv_skb,
>> > > phy->mode);
>> > > +             phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN,
>> > > GFP_KERNEL);
>> > > +             if (!phy->recv_skb)
>> > > +                     return 0;
>> > > +     }
>> > > +
>> > > +     return i;
>> > > +}
>> > > +
>> > > +static struct serdev_device_ops s3fwrn82_serdev_ops = {
>> >
>> > const
>> >
>> > > +     .receive_buf = s3fwrn82_uart_read,
>> > > +     .write_wakeup = serdev_device_write_wakeup,
>> > > +};
>> > > +
>> > > +static const struct of_device_id s3fwrn82_uart_of_match[] = {
>> > > +     { .compatible = "samsung,s3fwrn82-uart", },
>> > > +     {},
>> > > +};
>> > > +MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
>> > > +
>> > > +static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
>> > > +{
>> > > +     struct s3fwrn82_uart_phy *phy =
>> > > serdev_device_get_drvdata(serdev);
>> > > +     struct device_node *np = serdev->dev.of_node;
>> > > +
>> > > +     if (!np)
>> > > +             return -ENODEV;
>> > > +
>> > > +     phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
>> > > +     if (!gpio_is_valid(phy->gpio_en))
>> > > +             return -ENODEV;
>> > > +
>> > > +     phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
>> >
>> > You should not cast it it unsigned int. I'll fix the s3fwrn5 from which
>> > you copied this apparently.
>> >
>>
>> Okay. I will fix it.
>>
>> > > +     if (!gpio_is_valid(phy->gpio_fw_wake))
>> > > +             return -ENODEV;
>> > > +
>> > > +     return 0;
>> > > +}
>> > > +
>> > > +static int s3fwrn82_uart_probe(struct serdev_device *serdev)
>> > > +{
>> > > +     struct s3fwrn82_uart_phy *phy;
>> > > +     int ret = -ENOMEM;
>> > > +
>> > > +     phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
>> > > +     if (!phy)
>> > > +             goto err_exit;
>> > > +
>> > > +     phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
>> > > +     if (!phy->recv_skb)
>> > > +             goto err_free;
>> > > +
>> > > +     mutex_init(&phy->mutex);
>> > > +     phy->mode = S3FWRN5_MODE_COLD;
>> > > +
>> > > +     phy->ser_dev = serdev;
>> > > +     serdev_device_set_drvdata(serdev, phy);
>> > > +     serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
>> > > +     ret = serdev_device_open(serdev);
>> > > +     if (ret) {
>> > > +             dev_err(&serdev->dev, "Unable to open device\n");
>> > > +             goto err_skb;
>> > > +     }
>> > > +
>> > > +     ret = serdev_device_set_baudrate(serdev, 115200);
>> >
>> > Why baudrate is fixed?
>> >
>>
>> RN82 NFC chip only supports 115200 baudrate for UART.
>
> OK, I guess it could be extended in the future for other frequencies, if
> needed.
>
>>
>> > > +     if (ret != 115200) {
>> > > +             ret = -EINVAL;
>> > > +             goto err_serdev;
>> > > +     }
>> > > +
>> > > +     serdev_device_set_flow_control(serdev, false);
>> > > +
>> > > +     ret = s3fwrn82_uart_parse_dt(serdev);
>> > > +     if (ret < 0)
>> > > +             goto err_serdev;
>> > > +
>> > > +     ret = devm_gpio_request_one(&phy->ser_dev->dev,
>> > > +                                 phy->gpio_en,
>> > > +                                 GPIOF_OUT_INIT_HIGH,
>> > > +                                 "s3fwrn82_en");
>> >
>> > This is weirdly wrapped.
>> >
>>
>> Did you ask about devem_gpio_request_one function's parenthesis and
>> parameters?
>> If it is right, I changed it after i ran the checkpatch.pl --strict and
>> i saw message like the alignment should match open parenthesis.
>
> Yeah, but it does not mean to wrap after each argument. It should be
> something like:
>
>         ret = devm_gpio_request_one(&phy->ser_dev->dev, phy->gpio_en,
>                                     GPIOF_OUT_INIT_HIGH, "s3fwrn82_en");
>
>>
>> > > +     if (ret < 0)
>> > > +             goto err_serdev;
>> > > +
>> > > +     ret = devm_gpio_request_one(&phy->ser_dev->dev,
>> > > +                                 phy->gpio_fw_wake,
>> > > +                                 GPIOF_OUT_INIT_LOW,
>> > > +                                 "s3fwrn82_fw_wake");
>> > > +     if (ret < 0)
>> > > +             goto err_serdev;
>> > > +
>> > > +     ret = s3fwrn5_probe(&phy->ndev, phy, &phy->ser_dev->dev,
>> > > &uart_phy_ops);
>> > > +     if (ret < 0)
>> > > +             goto err_serdev;
>> > > +
>> > > +     return ret;
>> > > +
>> > > +err_serdev:
>> > > +     serdev_device_close(serdev);
>> > > +err_skb:
>> > > +     kfree_skb(phy->recv_skb);
>> > > +err_free:
>> > > +     kfree(phy);
>> >
>> > Eee.... why? Did you test this code?
>> >
>>
>> I didn't test this code. i just added this code as defense code.
>> If the error happens, then allocated memory and device will be free
>> according to the fail case.
>
> Really, this won't work. It's kind of obvious why... You cannot use
> kfree() on memory which is not allocated with kzalloc(). Or IOW, you
> cannot use it if it is being freed by devm.
>
> I doubt that you tested either this or the remove callback because if
> you did test it, you would see easily:
>

Thanks to explain it in detail.

> Please fix the double-free.
>

I understand it and will remove the kfree(phy).
And i did the remove callback test using following echo command's
parameters on raspberry pi.
But i didn't see the error log like yours.

Echo serial0-0 > /sys/bus/serial/devices/serial0/serial0-0/driver/unbind

> Best regards,
> Krzysztof
>
>

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next 2/2] net: nfc: s3fwrn5: Support a UART interface
  2020-11-25  4:01 90%         ` Bongsu Jeon
@ 2020-11-25  4:43 90%           ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-25  4:43 UTC (permalink / raw)
  To: krzk; +Cc: Bongsu Jeon, kuba, linux-kernel, linux-nfc, netdev

On 11/25/20, Bongsu Jeon <bongsu.jeon2@gmail.com> wrote:
> On 11/24/20, krzk@kernel.org <krzk@kernel.org> wrote:
>> On Tue, Nov 24, 2020 at 09:05:52PM +0900, Bongsu Jeon wrote:
>>> On Mon, Nov 23, 2020 at 5:55 PM krzk@kernel.org <krzk@kernel.org> wrote:
>>> > > +static enum s3fwrn5_mode s3fwrn82_uart_get_mode(void *phy_id)
>>> > > +{
>>> > > +     struct s3fwrn82_uart_phy *phy = phy_id;
>>> > > +     enum s3fwrn5_mode mode;
>>> > > +
>>> > > +     mutex_lock(&phy->mutex);
>>> > > +     mode = phy->mode;
>>> > > +     mutex_unlock(&phy->mutex);
>>> > > +     return mode;
>>> > > +}
>>> >
>>> > All this duplicates I2C version. You need to start either reusing
>>> > common
>>> > blocks.
>>> >
>>>
>>> Okay. I will do refactoring on i2c.c and uart.c to make common blocks.
>>>  is it okay to separate a patch for it?
>>
>> Yes, that would be the best - refactor the driver to split some common
>> methods and then in next patch add new s3fwrn82 UART driver.
>>
>>> > > +
>>> > > +static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
>>> > > +{
>>> > > +     struct s3fwrn82_uart_phy *phy = phy_id;
>>> > > +     int err;
>>> > > +
>>> > > +     err = serdev_device_write(phy->ser_dev,
>>> > > +                               out->data, out->len,
>>> > > +                               MAX_SCHEDULE_TIMEOUT);
>>> > > +     if (err < 0)
>>> > > +             return err;
>>> > > +
>>> > > +     return 0;
>>> > > +}
>>> > > +
>>> > > +static const struct s3fwrn5_phy_ops uart_phy_ops = {
>>> > > +     .set_wake = s3fwrn82_uart_set_wake,
>>> > > +     .set_mode = s3fwrn82_uart_set_mode,
>>> > > +     .get_mode = s3fwrn82_uart_get_mode,
>>> > > +     .write = s3fwrn82_uart_write,
>>> > > +};
>>> > > +
>>> > > +static int s3fwrn82_uart_read(struct serdev_device *serdev,
>>> > > +                           const unsigned char *data,
>>> > > +                           size_t count)
>>> > > +{
>>> > > +     struct s3fwrn82_uart_phy *phy =
>>> > > serdev_device_get_drvdata(serdev);
>>> > > +     size_t i;
>>> > > +
>>> > > +     for (i = 0; i < count; i++) {
>>> > > +             skb_put_u8(phy->recv_skb, *data++);
>>> > > +
>>> > > +             if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
>>> > > +                     continue;
>>> > > +
>>> > > +             if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
>>> > > +                             <
>>> > > phy->recv_skb->data[S3FWRN82_NCI_IDX])
>>> > > +                     continue;
>>> > > +
>>> > > +             s3fwrn5_recv_frame(phy->ndev, phy->recv_skb,
>>> > > phy->mode);
>>> > > +             phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN,
>>> > > GFP_KERNEL);
>>> > > +             if (!phy->recv_skb)
>>> > > +                     return 0;
>>> > > +     }
>>> > > +
>>> > > +     return i;
>>> > > +}
>>> > > +
>>> > > +static struct serdev_device_ops s3fwrn82_serdev_ops = {
>>> >
>>> > const
>>> >
>>> > > +     .receive_buf = s3fwrn82_uart_read,
>>> > > +     .write_wakeup = serdev_device_write_wakeup,
>>> > > +};
>>> > > +
>>> > > +static const struct of_device_id s3fwrn82_uart_of_match[] = {
>>> > > +     { .compatible = "samsung,s3fwrn82-uart", },
>>> > > +     {},
>>> > > +};
>>> > > +MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
>>> > > +
>>> > > +static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
>>> > > +{
>>> > > +     struct s3fwrn82_uart_phy *phy =
>>> > > serdev_device_get_drvdata(serdev);
>>> > > +     struct device_node *np = serdev->dev.of_node;
>>> > > +
>>> > > +     if (!np)
>>> > > +             return -ENODEV;
>>> > > +
>>> > > +     phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
>>> > > +     if (!gpio_is_valid(phy->gpio_en))
>>> > > +             return -ENODEV;
>>> > > +
>>> > > +     phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
>>> >
>>> > You should not cast it it unsigned int. I'll fix the s3fwrn5 from
>>> > which
>>> > you copied this apparently.
>>> >
>>>
>>> Okay. I will fix it.
>>>
>>> > > +     if (!gpio_is_valid(phy->gpio_fw_wake))
>>> > > +             return -ENODEV;
>>> > > +
>>> > > +     return 0;
>>> > > +}
>>> > > +
>>> > > +static int s3fwrn82_uart_probe(struct serdev_device *serdev)
>>> > > +{
>>> > > +     struct s3fwrn82_uart_phy *phy;
>>> > > +     int ret = -ENOMEM;
>>> > > +
>>> > > +     phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
>>> > > +     if (!phy)
>>> > > +             goto err_exit;
>>> > > +
>>> > > +     phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
>>> > > +     if (!phy->recv_skb)
>>> > > +             goto err_free;
>>> > > +
>>> > > +     mutex_init(&phy->mutex);
>>> > > +     phy->mode = S3FWRN5_MODE_COLD;
>>> > > +
>>> > > +     phy->ser_dev = serdev;
>>> > > +     serdev_device_set_drvdata(serdev, phy);
>>> > > +     serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
>>> > > +     ret = serdev_device_open(serdev);
>>> > > +     if (ret) {
>>> > > +             dev_err(&serdev->dev, "Unable to open device\n");
>>> > > +             goto err_skb;
>>> > > +     }
>>> > > +
>>> > > +     ret = serdev_device_set_baudrate(serdev, 115200);
>>> >
>>> > Why baudrate is fixed?
>>> >
>>>
>>> RN82 NFC chip only supports 115200 baudrate for UART.
>>
>> OK, I guess it could be extended in the future for other frequencies, if
>> needed.
>>
>>>
>>> > > +     if (ret != 115200) {
>>> > > +             ret = -EINVAL;
>>> > > +             goto err_serdev;
>>> > > +     }
>>> > > +
>>> > > +     serdev_device_set_flow_control(serdev, false);
>>> > > +
>>> > > +     ret = s3fwrn82_uart_parse_dt(serdev);
>>> > > +     if (ret < 0)
>>> > > +             goto err_serdev;
>>> > > +
>>> > > +     ret = devm_gpio_request_one(&phy->ser_dev->dev,
>>> > > +                                 phy->gpio_en,
>>> > > +                                 GPIOF_OUT_INIT_HIGH,
>>> > > +                                 "s3fwrn82_en");
>>> >
>>> > This is weirdly wrapped.
>>> >
>>>
>>> Did you ask about devem_gpio_request_one function's parenthesis and
>>> parameters?
>>> If it is right, I changed it after i ran the checkpatch.pl --strict and
>>> i saw message like the alignment should match open parenthesis.
>>
>> Yeah, but it does not mean to wrap after each argument. It should be
>> something like:
>>
>>         ret = devm_gpio_request_one(&phy->ser_dev->dev, phy->gpio_en,
>>                                     GPIOF_OUT_INIT_HIGH, "s3fwrn82_en");
>>
>>>
>>> > > +     if (ret < 0)
>>> > > +             goto err_serdev;
>>> > > +
>>> > > +     ret = devm_gpio_request_one(&phy->ser_dev->dev,
>>> > > +                                 phy->gpio_fw_wake,
>>> > > +                                 GPIOF_OUT_INIT_LOW,
>>> > > +                                 "s3fwrn82_fw_wake");
>>> > > +     if (ret < 0)
>>> > > +             goto err_serdev;
>>> > > +
>>> > > +     ret = s3fwrn5_probe(&phy->ndev, phy, &phy->ser_dev->dev,
>>> > > &uart_phy_ops);
>>> > > +     if (ret < 0)
>>> > > +             goto err_serdev;
>>> > > +
>>> > > +     return ret;
>>> > > +
>>> > > +err_serdev:
>>> > > +     serdev_device_close(serdev);
>>> > > +err_skb:
>>> > > +     kfree_skb(phy->recv_skb);
>>> > > +err_free:
>>> > > +     kfree(phy);
>>> >
>>> > Eee.... why? Did you test this code?
>>> >
>>>
>>> I didn't test this code. i just added this code as defense code.
>>> If the error happens, then allocated memory and device will be free
>>> according to the fail case.
>>
>> Really, this won't work. It's kind of obvious why... You cannot use
>> kfree() on memory which is not allocated with kzalloc(). Or IOW, you
>> cannot use it if it is being freed by devm.
>>
>> I doubt that you tested either this or the remove callback because if
>> you did test it, you would see easily:
>>
>
> Thanks to explain it in detail.
>
>> Please fix the double-free.
>>
>
> I understand it and will remove the kfree(phy).
> And i did the remove callback test using following echo command's
> parameters on raspberry pi.
> But i didn't see the error log like yours.
>
> Echo serial0-0 > /sys/bus/serial/devices/serial0/serial0-0/driver/unbind
>

Sorry to reply this email in a row.
I could see the log like yours when i changed the code at uart probe
functiom to make an error situation by force as below.
ret = -EINVAL;
     // s3fwrn5_probe(~~~

and i couldn't see the log when i removed the kfree(phy).
Thanks to mention it.


>> Best regards,
>> Krzysztof
>>
>>
>

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next 1/3] nfc: s3fwrn5: use signed integer for parsing GPIO numbers
  @ 2020-11-26 22:53 78%   ` Bongsu Jeon
  2020-11-27  5:41 90%     ` Bongsu Jeon
  0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-11-26 22:53 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Bongsu Jeon, Krzysztof Opasiak, linux-nfc, netdev, linux-kernel, stable

On Fri, Nov 27, 2020 at 2:06 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Fri, Nov 27, 2020 at 12:33:37AM +0900, bongsu.jeon2@gmail.com wrote:
> > From: Krzysztof Kozlowski <krzk@kernel.org>
> >
> > GPIOs - as returned by of_get_named_gpio() and used by the gpiolib - are
> > signed integers, where negative number indicates error.  The return
> > value of of_get_named_gpio() should not be assigned to an unsigned int
> > because in case of !CONFIG_GPIOLIB such number would be a valid GPIO.
> >
> > Fixes: c04c674fadeb ("nfc: s3fwrn5: Add driver for Samsung S3FWRN5 NFC Chip")
> > Cc: <stable@vger.kernel.org>
> > Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Why do you send my patch?
>

I think that your patch should be applied before refactoring for this driver.
So, I applied your patch to net-next branch and included your patch at
my patch list.
Is this the wrong process?

> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 78%]

* Re: [PATCH net-next 3/3] nfc: s3fwrn5: extract the common phy blocks
  @ 2020-11-26 23:09 90%     ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-26 23:09 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: k.opasiak, linux-nfc, netdev, linux-kernel, Bongsu Jeon

On Fri, Nov 27, 2020 at 2:13 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Fri, Nov 27, 2020 at 12:33:39AM +0900, bongsu.jeon2@gmail.com wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > Extract the common phy blocks to reuse it.
> > The UART module will use the common blocks.
>
>
> Hi,
>
> Thanks for the patch. Few comments below.
>
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> > ---
> >  drivers/nfc/s3fwrn5/i2c.c        | 111 ++++++++++++---------------------------
> >  drivers/nfc/s3fwrn5/phy_common.h |  86 ++++++++++++++++++++++++++++++
> >  2 files changed, 119 insertions(+), 78 deletions(-)
> >  create mode 100644 drivers/nfc/s3fwrn5/phy_common.h
> >
> > diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
> > index 9a64eea..cd1b2a7 100644
> > --- a/drivers/nfc/s3fwrn5/i2c.c
> > +++ b/drivers/nfc/s3fwrn5/i2c.c
> > @@ -15,75 +15,30 @@
> >
> >  #include <net/nfc/nfc.h>
> >
> > -#include "s3fwrn5.h"
> > +#include "phy_common.h"
> >
> >  #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
> >
> > -#define S3FWRN5_EN_WAIT_TIME 20
> > -
> >  struct s3fwrn5_i2c_phy {
> > +     struct phy_common common;
> >       struct i2c_client *i2c_dev;
> > -     struct nci_dev *ndev;
> > -
> > -     int gpio_en;
> > -     int gpio_fw_wake;
> > -
> > -     struct mutex mutex;
> >
> > -     enum s3fwrn5_mode mode;
> >       unsigned int irq_skip:1;
> >  };
> >
> > -static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
> > -{
> > -     struct s3fwrn5_i2c_phy *phy = phy_id;
> > -
> > -     mutex_lock(&phy->mutex);
> > -     gpio_set_value(phy->gpio_fw_wake, wake);
> > -     msleep(S3FWRN5_EN_WAIT_TIME);
> > -     mutex_unlock(&phy->mutex);
> > -}
> > -
> >  static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
> >  {
> >       struct s3fwrn5_i2c_phy *phy = phy_id;
> >
> > -     mutex_lock(&phy->mutex);
> > +     mutex_lock(&phy->common.mutex);
> >
> > -     if (phy->mode == mode)
> > +     if (s3fwrn5_phy_power_ctrl(&phy->common, mode) == false)
> >               goto out;
> >
> > -     phy->mode = mode;
> > -
> > -     gpio_set_value(phy->gpio_en, 1);
> > -     gpio_set_value(phy->gpio_fw_wake, 0);
> > -     if (mode == S3FWRN5_MODE_FW)
> > -             gpio_set_value(phy->gpio_fw_wake, 1);
> > -
> > -     if (mode != S3FWRN5_MODE_COLD) {
> > -             msleep(S3FWRN5_EN_WAIT_TIME);
> > -             gpio_set_value(phy->gpio_en, 0);
> > -             msleep(S3FWRN5_EN_WAIT_TIME);
> > -     }
> > -
> >       phy->irq_skip = true;
> >
> >  out:
> > -     mutex_unlock(&phy->mutex);
> > -}
> > -
> > -static enum s3fwrn5_mode s3fwrn5_i2c_get_mode(void *phy_id)
> > -{
> > -     struct s3fwrn5_i2c_phy *phy = phy_id;
> > -     enum s3fwrn5_mode mode;
> > -
> > -     mutex_lock(&phy->mutex);
> > -
> > -     mode = phy->mode;
> > -
> > -     mutex_unlock(&phy->mutex);
> > -
> > -     return mode;
> > +     mutex_unlock(&phy->common.mutex);
> >  }
> >
> >  static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> > @@ -91,7 +46,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> >       struct s3fwrn5_i2c_phy *phy = phy_id;
> >       int ret;
> >
> > -     mutex_lock(&phy->mutex);
> > +     mutex_lock(&phy->common.mutex);
> >
> >       phy->irq_skip = false;
> >
> > @@ -102,7 +57,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> >               ret  = i2c_master_send(phy->i2c_dev, skb->data, skb->len);
> >       }
> >
> > -     mutex_unlock(&phy->mutex);
> > +     mutex_unlock(&phy->common.mutex);
> >
> >       if (ret < 0)
> >               return ret;
> > @@ -114,9 +69,9 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> >  }
> >
> >  static const struct s3fwrn5_phy_ops i2c_phy_ops = {
> > -     .set_wake = s3fwrn5_i2c_set_wake,
> > +     .set_wake = s3fwrn5_phy_set_wake,
> >       .set_mode = s3fwrn5_i2c_set_mode,
> > -     .get_mode = s3fwrn5_i2c_get_mode,
> > +     .get_mode = s3fwrn5_phy_get_mode,
> >       .write = s3fwrn5_i2c_write,
> >  };
> >
> > @@ -128,7 +83,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
> >       char hdr[4];
> >       int ret;
> >
> > -     hdr_size = (phy->mode == S3FWRN5_MODE_NCI) ?
> > +     hdr_size = (phy->common.mode == S3FWRN5_MODE_NCI) ?
> >               NCI_CTRL_HDR_SIZE : S3FWRN5_FW_HDR_SIZE;
> >       ret = i2c_master_recv(phy->i2c_dev, hdr, hdr_size);
> >       if (ret < 0)
> > @@ -137,7 +92,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
> >       if (ret < hdr_size)
> >               return -EBADMSG;
> >
> > -     data_len = (phy->mode == S3FWRN5_MODE_NCI) ?
> > +     data_len = (phy->common.mode == S3FWRN5_MODE_NCI) ?
> >               ((struct nci_ctrl_hdr *)hdr)->plen :
> >               ((struct s3fwrn5_fw_header *)hdr)->len;
> >
> > @@ -157,24 +112,24 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
> >       }
> >
> >  out:
> > -     return s3fwrn5_recv_frame(phy->ndev, skb, phy->mode);
> > +     return s3fwrn5_recv_frame(phy->common.ndev, skb, phy->common.mode);
> >  }
> >
> >  static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
> >  {
> >       struct s3fwrn5_i2c_phy *phy = phy_id;
> >
> > -     if (!phy || !phy->ndev) {
> > +     if (!phy || !phy->common.ndev) {
> >               WARN_ON_ONCE(1);
> >               return IRQ_NONE;
> >       }
> >
> > -     mutex_lock(&phy->mutex);
> > +     mutex_lock(&phy->common.mutex);
> >
> >       if (phy->irq_skip)
> >               goto out;
> >
> > -     switch (phy->mode) {
> > +     switch (phy->common.mode) {
> >       case S3FWRN5_MODE_NCI:
> >       case S3FWRN5_MODE_FW:
> >               s3fwrn5_i2c_read(phy);
> > @@ -184,7 +139,7 @@ static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
> >       }
> >
> >  out:
> > -     mutex_unlock(&phy->mutex);
> > +     mutex_unlock(&phy->common.mutex);
> >
> >       return IRQ_HANDLED;
> >  }
> > @@ -197,19 +152,19 @@ static int s3fwrn5_i2c_parse_dt(struct i2c_client *client)
> >       if (!np)
> >               return -ENODEV;
> >
> > -     phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
> > -     if (!gpio_is_valid(phy->gpio_en)) {
> > +     phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
> > +     if (!gpio_is_valid(phy->common.gpio_en)) {
> >               /* Support also deprecated property */
> > -             phy->gpio_en = of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
> > -             if (!gpio_is_valid(phy->gpio_en))
> > +             phy->common.gpio_en = of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
> > +             if (!gpio_is_valid(phy->common.gpio_en))
> >                       return -ENODEV;
> >       }
> >
> > -     phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
> > -     if (!gpio_is_valid(phy->gpio_fw_wake)) {
> > +     phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
> > +     if (!gpio_is_valid(phy->common.gpio_fw_wake)) {
> >               /* Support also deprecated property */
> > -             phy->gpio_fw_wake = of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
> > -             if (!gpio_is_valid(phy->gpio_fw_wake))
> > +             phy->common.gpio_fw_wake = of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
>
> The lines here should wrap at 80 character.
>
> > +             if (!gpio_is_valid(phy->common.gpio_fw_wake))
> >                       return -ENODEV;
> >       }
> >
> > @@ -226,8 +181,8 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >       if (!phy)
> >               return -ENOMEM;
> >
> > -     mutex_init(&phy->mutex);
> > -     phy->mode = S3FWRN5_MODE_COLD;
> > +     mutex_init(&phy->common.mutex);
> > +     phy->common.mode = S3FWRN5_MODE_COLD;
> >       phy->irq_skip = true;
> >
> >       phy->i2c_dev = client;
> > @@ -237,17 +192,17 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >       if (ret < 0)
> >               return ret;
> >
> > -     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
> > -             GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
> > +     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->common.gpio_en,
> > +                                 GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
> >       if (ret < 0)
> >               return ret;
> >
> > -     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw_wake,
> > -             GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
> > +     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->common.gpio_fw_wake,
> > +                                 GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
> >       if (ret < 0)
> >               return ret;
> >
> > -     ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
> > +     ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
>
> Please wrap the lines.
>
> >       if (ret < 0)
> >               return ret;
> >
> > @@ -255,7 +210,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >               s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> >               S3FWRN5_I2C_DRIVER_NAME, phy);
> >       if (ret)
> > -             s3fwrn5_remove(phy->ndev);
> > +             s3fwrn5_remove(phy->common.ndev);
> >
> >       return ret;
> >  }
> > @@ -264,7 +219,7 @@ static int s3fwrn5_i2c_remove(struct i2c_client *client)
> >  {
> >       struct s3fwrn5_i2c_phy *phy = i2c_get_clientdata(client);
> >
> > -     s3fwrn5_remove(phy->ndev);
> > +     s3fwrn5_remove(phy->common.ndev);
> >
> >       return 0;
> >  }
> > diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
> > new file mode 100644
> > index 0000000..14f7690
> > --- /dev/null
> > +++ b/drivers/nfc/s3fwrn5/phy_common.h
> > @@ -0,0 +1,86 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later
> > + *
> > + * Link Layer for Samsung S3FWRN5 NCI based Driver
> > + *
> > + * Copyright (C) 2015 Samsung Electrnoics
> > + * Robert Baldyga <r.baldyga@samsung.com>
> > + * Copyright (C) 2020 Samsung Electrnoics
> > + * Bongsu Jeon <bongsu.jeon@samsung.com>
> > + */
> > +
> > +#ifndef __LOCAL_PHY_COMMON_H
> > +#define __LOCAL_PHY_COMMON_H
>
> Header guard: __NFC_S3FWRN5_PHY_COMMON_H
>
> > +
> > +#include "s3fwrn5.h"
>
> This include should not be needed.
>

Actually, I included this because of enum s3fwrn5_mode.
Do you think the following structure is good?

0. remove the '#include "s3fwrn5.h" and the common function's
definition in phy_common.h.
1. make phy_common.c that includes the common function's definition
and "s3fwrn5.h , phy_common.h".
2. i2c.c includes "s3fwrn5.h , phy_common.h".

> > +
> > +#define S3FWRN5_EN_WAIT_TIME 20
> > +
> > +struct phy_common {
> > +     struct nci_dev *ndev;
> > +
> > +     int gpio_en;
> > +     int gpio_fw_wake;
> > +
> > +     struct mutex mutex;
> > +
> > +     enum s3fwrn5_mode mode;
> > +};
> > +
> > +static inline void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
> > +{
>
> All these should go to a C source file. If needed - GPL exported.
>
> > +     struct phy_common *phy = phy_id;
> > +
> > +     mutex_lock(&phy->mutex);
> > +     gpio_set_value(phy->gpio_fw_wake, wake);
> > +     msleep(S3FWRN5_EN_WAIT_TIME);
> > +     mutex_unlock(&phy->mutex);
> > +}
> > +
> > +static inline bool s3fwrn5_phy_power_ctrl(struct phy_common *phy,
> > +                                       enum s3fwrn5_mode mode)
> > +{
> > +     if (phy->mode == mode)
> > +             return false;
> > +
> > +     phy->mode = mode;
> > +
> > +     gpio_set_value(phy->gpio_en, 1);
> > +     gpio_set_value(phy->gpio_fw_wake, 0);
> > +     if (mode == S3FWRN5_MODE_FW)
> > +             gpio_set_value(phy->gpio_fw_wake, 1);
> > +
> > +     if (mode != S3FWRN5_MODE_COLD) {
> > +             msleep(S3FWRN5_EN_WAIT_TIME);
> > +             gpio_set_value(phy->gpio_en, 0);
> > +             msleep(S3FWRN5_EN_WAIT_TIME);
> > +     }
> > +
> > +     return true;
> > +}
> > +
> > +static inline void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode)
> > +{
>
> This looks unused. If you need it only for your next chip, add it with
> next patch (the patch adding the user).
>
Okay I understand it.

> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next 1/3] nfc: s3fwrn5: use signed integer for parsing GPIO numbers
  2020-11-26 22:53 78%   ` Bongsu Jeon
@ 2020-11-27  5:41 90%     ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-27  5:41 UTC (permalink / raw)
  To: krzk; +Cc: Krzysztof Opasiak, linux-nfc, netdev, linux-kernel, stable

On 11/27/20, Bongsu Jeon <bs.jeon87@gmail.com> wrote:
> On Fri, Nov 27, 2020 at 2:06 AM Krzysztof Kozlowski <krzk@kernel.org>
> wrote:
>>
>> On Fri, Nov 27, 2020 at 12:33:37AM +0900, bongsu.jeon2@gmail.com wrote:
>> > From: Krzysztof Kozlowski <krzk@kernel.org>
>> >
>> > GPIOs - as returned by of_get_named_gpio() and used by the gpiolib -
>> > are
>> > signed integers, where negative number indicates error.  The return
>> > value of of_get_named_gpio() should not be assigned to an unsigned int
>> > because in case of !CONFIG_GPIOLIB such number would be a valid GPIO.
>> >
>> > Fixes: c04c674fadeb ("nfc: s3fwrn5: Add driver for Samsung S3FWRN5 NFC
>> > Chip")
>> > Cc: <stable@vger.kernel.org>
>> > Signed-off-by: Krzysztof Kozlowski <krzk@kernel.org>
>>
>> Why do you send my patch?
>>
>
> I think that your patch should be applied before refactoring for this
> driver.
> So, I applied your patch to net-next branch and included your patch at
> my patch list.
> Is this the wrong process?
>

Sorry to confuse you.
I found your patch when i updated my workspace using git pull.

>> Best regards,
>> Krzysztof
>

^ permalink raw reply	[relevance 90%]

* Re: [PATCH v2 net-next 3/3] nfc: s3fwrn5: extract the common phy blocks
  @ 2020-11-29  9:55 89%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-29  9:55 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Krzysztof Opasiak, linux-nfc, netdev, linux-kernel, Bongsu Jeon

On Sat, Nov 28, 2020 at 9:49 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Fri, Nov 27, 2020 at 08:22:18PM +0900, bongsu.jeon2@gmail.com wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > Extract the common phy blocks to reuse it.
> > The UART module will use the common blocks.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> > ---
> > Changes in v2:
> >  - remove the common function's definition in common header file.
> >  - make the common phy_common.c file to define the common function.
> >  - wrap the lines.
> >  - change the Header guard.
> >  - remove the unused common function.
> >
> >  drivers/nfc/s3fwrn5/Makefile     |   2 +-
> >  drivers/nfc/s3fwrn5/i2c.c        | 114 +++++++++++++--------------------------
> >  drivers/nfc/s3fwrn5/phy_common.c |  60 +++++++++++++++++++++
> >  drivers/nfc/s3fwrn5/phy_common.h |  31 +++++++++++
> >  4 files changed, 129 insertions(+), 78 deletions(-)
> >  create mode 100644 drivers/nfc/s3fwrn5/phy_common.c
> >  create mode 100644 drivers/nfc/s3fwrn5/phy_common.h
> >
> > diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
> > index d0ffa35..a5279c6 100644
> > --- a/drivers/nfc/s3fwrn5/Makefile
> > +++ b/drivers/nfc/s3fwrn5/Makefile
> > @@ -4,7 +4,7 @@
> >  #
> >
> >  s3fwrn5-objs = core.o firmware.o nci.o
> > -s3fwrn5_i2c-objs = i2c.o
> > +s3fwrn5_i2c-objs = i2c.o phy_common.o
>
> Thanks for the changes.
>
> Shouldn't this be part of s3fwrn5.ko? Otherwise you would duplicate the
> objects in two modules.
>

Okay. It could be better to avoid the duplication.
I will try to move phy_common.c to s3fwrn5.ko.

> >
> >  obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
> >  obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
> > diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
> > index 9a64eea..207f970 100644
> > --- a/drivers/nfc/s3fwrn5/i2c.c
> > +++ b/drivers/nfc/s3fwrn5/i2c.c
> > @@ -16,74 +16,30 @@
> >  #include <net/nfc/nfc.h>
> >
> >  #include "s3fwrn5.h"
> > +#include "phy_common.h"
> >
> >  #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
> >
> > -#define S3FWRN5_EN_WAIT_TIME 20
> > -
> >  struct s3fwrn5_i2c_phy {
> > +     struct phy_common common;
> >       struct i2c_client *i2c_dev;
> > -     struct nci_dev *ndev;
> > -
> > -     int gpio_en;
> > -     int gpio_fw_wake;
> > -
> > -     struct mutex mutex;
> >
> > -     enum s3fwrn5_mode mode;
> >       unsigned int irq_skip:1;
> >  };
> >
> > -static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
> > -{
> > -     struct s3fwrn5_i2c_phy *phy = phy_id;
> > -
> > -     mutex_lock(&phy->mutex);
> > -     gpio_set_value(phy->gpio_fw_wake, wake);
> > -     msleep(S3FWRN5_EN_WAIT_TIME);
> > -     mutex_unlock(&phy->mutex);
> > -}
> > -
> >  static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
> >  {
> >       struct s3fwrn5_i2c_phy *phy = phy_id;
> >
> > -     mutex_lock(&phy->mutex);
> > +     mutex_lock(&phy->common.mutex);
> >
> > -     if (phy->mode == mode)
> > +     if (s3fwrn5_phy_power_ctrl(&phy->common, mode) == false)
> >               goto out;
> >
> > -     phy->mode = mode;
> > -
> > -     gpio_set_value(phy->gpio_en, 1);
> > -     gpio_set_value(phy->gpio_fw_wake, 0);
> > -     if (mode == S3FWRN5_MODE_FW)
> > -             gpio_set_value(phy->gpio_fw_wake, 1);
> > -
> > -     if (mode != S3FWRN5_MODE_COLD) {
> > -             msleep(S3FWRN5_EN_WAIT_TIME);
> > -             gpio_set_value(phy->gpio_en, 0);
> > -             msleep(S3FWRN5_EN_WAIT_TIME);
> > -     }
> > -
> >       phy->irq_skip = true;
> >
> >  out:
> > -     mutex_unlock(&phy->mutex);
> > -}
> > -
> > -static enum s3fwrn5_mode s3fwrn5_i2c_get_mode(void *phy_id)
> > -{
> > -     struct s3fwrn5_i2c_phy *phy = phy_id;
> > -     enum s3fwrn5_mode mode;
> > -
> > -     mutex_lock(&phy->mutex);
> > -
> > -     mode = phy->mode;
> > -
> > -     mutex_unlock(&phy->mutex);
> > -
> > -     return mode;
> > +     mutex_unlock(&phy->common.mutex);
> >  }
> >
> >  static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> > @@ -91,7 +47,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> >       struct s3fwrn5_i2c_phy *phy = phy_id;
> >       int ret;
> >
> > -     mutex_lock(&phy->mutex);
> > +     mutex_lock(&phy->common.mutex);
> >
> >       phy->irq_skip = false;
> >
> > @@ -102,7 +58,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> >               ret  = i2c_master_send(phy->i2c_dev, skb->data, skb->len);
> >       }
> >
> > -     mutex_unlock(&phy->mutex);
> > +     mutex_unlock(&phy->common.mutex);
> >
> >       if (ret < 0)
> >               return ret;
> > @@ -114,9 +70,9 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
> >  }
> >
> >  static const struct s3fwrn5_phy_ops i2c_phy_ops = {
> > -     .set_wake = s3fwrn5_i2c_set_wake,
> > +     .set_wake = s3fwrn5_phy_set_wake,
> >       .set_mode = s3fwrn5_i2c_set_mode,
> > -     .get_mode = s3fwrn5_i2c_get_mode,
> > +     .get_mode = s3fwrn5_phy_get_mode,
> >       .write = s3fwrn5_i2c_write,
> >  };
> >
> > @@ -128,7 +84,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
> >       char hdr[4];
> >       int ret;
> >
> > -     hdr_size = (phy->mode == S3FWRN5_MODE_NCI) ?
> > +     hdr_size = (phy->common.mode == S3FWRN5_MODE_NCI) ?
> >               NCI_CTRL_HDR_SIZE : S3FWRN5_FW_HDR_SIZE;
> >       ret = i2c_master_recv(phy->i2c_dev, hdr, hdr_size);
> >       if (ret < 0)
> > @@ -137,7 +93,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
> >       if (ret < hdr_size)
> >               return -EBADMSG;
> >
> > -     data_len = (phy->mode == S3FWRN5_MODE_NCI) ?
> > +     data_len = (phy->common.mode == S3FWRN5_MODE_NCI) ?
> >               ((struct nci_ctrl_hdr *)hdr)->plen :
> >               ((struct s3fwrn5_fw_header *)hdr)->len;
> >
> > @@ -157,24 +113,24 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
> >       }
> >
> >  out:
> > -     return s3fwrn5_recv_frame(phy->ndev, skb, phy->mode);
> > +     return s3fwrn5_recv_frame(phy->common.ndev, skb, phy->common.mode);
> >  }
> >
> >  static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
> >  {
> >       struct s3fwrn5_i2c_phy *phy = phy_id;
> >
> > -     if (!phy || !phy->ndev) {
> > +     if (!phy || !phy->common.ndev) {
> >               WARN_ON_ONCE(1);
> >               return IRQ_NONE;
> >       }
> >
> > -     mutex_lock(&phy->mutex);
> > +     mutex_lock(&phy->common.mutex);
> >
> >       if (phy->irq_skip)
> >               goto out;
> >
> > -     switch (phy->mode) {
> > +     switch (phy->common.mode) {
> >       case S3FWRN5_MODE_NCI:
> >       case S3FWRN5_MODE_FW:
> >               s3fwrn5_i2c_read(phy);
> > @@ -184,7 +140,7 @@ static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
> >       }
> >
> >  out:
> > -     mutex_unlock(&phy->mutex);
> > +     mutex_unlock(&phy->common.mutex);
> >
> >       return IRQ_HANDLED;
> >  }
> > @@ -197,19 +153,21 @@ static int s3fwrn5_i2c_parse_dt(struct i2c_client *client)
> >       if (!np)
> >               return -ENODEV;
> >
> > -     phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
> > -     if (!gpio_is_valid(phy->gpio_en)) {
> > +     phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
> > +     if (!gpio_is_valid(phy->common.gpio_en)) {
> >               /* Support also deprecated property */
> > -             phy->gpio_en = of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
> > -             if (!gpio_is_valid(phy->gpio_en))
> > +             phy->common.gpio_en =
> > +                             of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
>
> This is not a proper wrapping. Wrapping happens on function arguments.
>
> > +             if (!gpio_is_valid(phy->common.gpio_en))
> >                       return -ENODEV;
> >       }
> >
> > -     phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
> > -     if (!gpio_is_valid(phy->gpio_fw_wake)) {
> > +     phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
> > +     if (!gpio_is_valid(phy->common.gpio_fw_wake)) {
> >               /* Support also deprecated property */
> > -             phy->gpio_fw_wake = of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
> > -             if (!gpio_is_valid(phy->gpio_fw_wake))
> > +             phy->common.gpio_fw_wake =
> > +                             of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
> > +             if (!gpio_is_valid(phy->common.gpio_fw_wake))
>
> The same.
>

Even though I wrapped this as below, Second line("s3fwrn5,fw-gpios" )
was over 80 columns.
Is it okay as below?
phy->gpio_fw_wake =of_get_named_gpio(np,

"s3fwrn5,fw-gpios",
                                                                     0);


> >                       return -ENODEV;
> >       }
> >
> > @@ -226,8 +184,8 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >       if (!phy)
> >               return -ENOMEM;
> >
> > -     mutex_init(&phy->mutex);
> > -     phy->mode = S3FWRN5_MODE_COLD;
> > +     mutex_init(&phy->common.mutex);
> > +     phy->common.mode = S3FWRN5_MODE_COLD;
> >       phy->irq_skip = true;
> >
> >       phy->i2c_dev = client;
> > @@ -237,17 +195,19 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >       if (ret < 0)
> >               return ret;
> >
> > -     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
> > -             GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
> > +     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->common.gpio_en,
> > +                                 GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
> >       if (ret < 0)
> >               return ret;
> >
> > -     ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw_wake,
> > -             GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
> > +     ret = devm_gpio_request_one(&phy->i2c_dev->dev,
> > +                                 phy->common.gpio_fw_wake,
> > +                                 GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
> >       if (ret < 0)
> >               return ret;
> >
> > -     ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
> > +     ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->i2c_dev->dev,
> > +                         &i2c_phy_ops);
> >       if (ret < 0)
> >               return ret;
> >
> > @@ -255,7 +215,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >               s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> >               S3FWRN5_I2C_DRIVER_NAME, phy);
> >       if (ret)
> > -             s3fwrn5_remove(phy->ndev);
> > +             s3fwrn5_remove(phy->common.ndev);
> >
> >       return ret;
> >  }
> > @@ -264,7 +224,7 @@ static int s3fwrn5_i2c_remove(struct i2c_client *client)
> >  {
> >       struct s3fwrn5_i2c_phy *phy = i2c_get_clientdata(client);
> >
> > -     s3fwrn5_remove(phy->ndev);
> > +     s3fwrn5_remove(phy->common.ndev);
> >
> >       return 0;
> >  }
> > diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
> > new file mode 100644
> > index 0000000..e333764
> > --- /dev/null
> > +++ b/drivers/nfc/s3fwrn5/phy_common.c
> > @@ -0,0 +1,60 @@
> > +// SPDX-License-Identifier: GPL-2.0-or-later
> > +/*
> > + * Link Layer for Samsung S3FWRN5 NCI based Driver
> > + *
> > + * Copyright (C) 2015 Samsung Electrnoics
> > + * Robert Baldyga <r.baldyga@samsung.com>
> > + * Copyright (C) 2020 Samsung Electrnoics
> > + * Bongsu Jeon <bongsu.jeon@samsung.com>
> > + */
> > +
> > +#include <linux/gpio.h>
> > +#include <linux/delay.h>
>
> You need also mutex.h (it seems original code did not have it but since
> you move things around it's a new code basically).
>
> > +
> > +#include "s3fwrn5.h"
> > +#include "phy_common.h"
> > +
> > +void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
> > +{
> > +     struct phy_common *phy = phy_id;
> > +
> > +     mutex_lock(&phy->mutex);
> > +     gpio_set_value(phy->gpio_fw_wake, wake);
> > +     msleep(S3FWRN5_EN_WAIT_TIME);
> > +     mutex_unlock(&phy->mutex);
> > +}
> > +
> > +bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
> > +{
> > +     if (phy->mode == mode)
> > +             return false;
> > +
> > +     phy->mode = mode;
> > +
> > +     gpio_set_value(phy->gpio_en, 1);
> > +     gpio_set_value(phy->gpio_fw_wake, 0);
> > +     if (mode == S3FWRN5_MODE_FW)
> > +             gpio_set_value(phy->gpio_fw_wake, 1);
> > +
> > +     if (mode != S3FWRN5_MODE_COLD) {
> > +             msleep(S3FWRN5_EN_WAIT_TIME);
> > +             gpio_set_value(phy->gpio_en, 0);
> > +             msleep(S3FWRN5_EN_WAIT_TIME);
> > +     }
> > +
> > +     return true;
> > +}
> > +
> > +enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
> > +{
> > +     struct phy_common *phy = phy_id;
> > +     enum s3fwrn5_mode mode;
> > +
> > +     mutex_lock(&phy->mutex);
> > +
> > +     mode = phy->mode;
> > +
> > +     mutex_unlock(&phy->mutex);
> > +
> > +     return mode;
> > +}
> > diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
> > new file mode 100644
> > index 0000000..b920f7f
> > --- /dev/null
> > +++ b/drivers/nfc/s3fwrn5/phy_common.h
> > @@ -0,0 +1,31 @@
> > +/* SPDX-License-Identifier: GPL-2.0-or-later
> > + *
> > + * Link Layer for Samsung S3FWRN5 NCI based Driver
> > + *
> > + * Copyright (C) 2015 Samsung Electrnoics
> > + * Robert Baldyga <r.baldyga@samsung.com>
> > + * Copyright (C) 2020 Samsung Electrnoics
> > + * Bongsu Jeon <bongsu.jeon@samsung.com>
> > + */
> > +
> > +#ifndef __NFC_S3FWRN5_PHY_COMMON_H
> > +#define __NFC_S3FWRN5_PHY_COMMON_H
> > +
> > +#define S3FWRN5_EN_WAIT_TIME 20
> > +
> > +struct phy_common {
> > +     struct nci_dev *ndev;
>
> You need a header for nci_dev type.
>
> > +
> > +     int gpio_en;
> > +     int gpio_fw_wake;
> > +
> > +     struct mutex mutex;
>
> You need a header include for mutex.
>
> > +
> > +     enum s3fwrn5_mode mode;
>
> Indeed now it won't work - you use an enum without its declaration. The
> s3fwrn5_mode enum looks more like a property of the phy and after this
> patch would be used only once in i2c.c and once in core.c.
>

Yes.  phy_common.h doesn't include nci_dev and mutex and s3fwrn5_mode
declaration.
So,  i2c.c and phy_common.c include "s3fwrn5.h" first and then "
( mutex and nci_dev would be included from nci_core.h and 3fwrn5_mode
would be included  from s3fwrn5.h).

> How is it going to be used in your new driver - I cannot check because
> you did not post it. You should post this refactoring with new users of
> the API, so we could see bigger picture.
>

Okay. Then, I will add the UART driver.
So, I will resend the patches as below.
1. [PATCH net-next 1/4] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
2. [PATCH net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME (*
because of Jakub's request )
3. [PATCH net-next 3/4] nfc: s3fwrn5: extract the common phy blocks
4. [PATCH net-next 4/4] net: nfc: s3fwrn5: Support a UART interface

> Your original idea - with the s3fwrn5.h include here - looks more
> logical than moving the enum s3fwrn5_mode here.
>

Do you mean that it would be better to include the s3fwrn5.h in phy_common.h?

> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 89%]

* [PATCH v2 net-next 1/4] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
@ 2020-11-30 12:00 90% Bongsu jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu jeon @ 2020-11-30 12:00 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---

Changes in v2:
 -change the compatible name.
 -change the const to enum for compatible.
 -change the node name to nfc.

 .../bindings/net/nfc/samsung,s3fwrn5.yaml          | 32 ++++++++++++++++++++--
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
index cb0b8a5..481bbcc 100644
--- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
@@ -12,7 +12,10 @@ maintainers:
 
 properties:
   compatible:
-    const: samsung,s3fwrn5-i2c
+    oneOf:
+      - enum:
+        - samsung,s3fwrn5-i2c
+        - samsung,s3fwrn82
 
   en-gpios:
     maxItems: 1
@@ -47,10 +50,19 @@ additionalProperties: false
 required:
   - compatible
   - en-gpios
-  - interrupts
-  - reg
   - wake-gpios
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s3fwrn5-i2c
+    then:
+      required:
+        - interrupts
+        - reg
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
@@ -71,3 +83,17 @@ examples:
             wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
         };
     };
+  # UART example on Raspberry Pi
+  - |
+    uart0 {
+        status = "okay";
+
+        nfc {
+            compatible = "samsung,s3fwrn82";
+
+            en-gpios = <&gpio 20 0>;
+            wake-gpios = <&gpio 16 0>;
+
+            status = "okay";
+        };
+    };
-- 
1.9.1


^ permalink raw reply related	[relevance 90%]

* [PATCH net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME
@ 2020-11-30 12:02 90% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-30 12:02 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

The delay of 20ms is enough to enable and
wake up the Samsung's nfc chip.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/i2c.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index ae26594..9a64eea 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -19,7 +19,7 @@
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_EN_WAIT_TIME 150
+#define S3FWRN5_EN_WAIT_TIME 20
 
 struct s3fwrn5_i2c_phy {
 	struct i2c_client *i2c_dev;
@@ -40,7 +40,7 @@ static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
 
 	mutex_lock(&phy->mutex);
 	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME/2);
+	msleep(S3FWRN5_EN_WAIT_TIME);
 	mutex_unlock(&phy->mutex);
 }
 
@@ -63,7 +63,7 @@ static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
 	if (mode != S3FWRN5_MODE_COLD) {
 		msleep(S3FWRN5_EN_WAIT_TIME);
 		gpio_set_value(phy->gpio_en, 0);
-		msleep(S3FWRN5_EN_WAIT_TIME/2);
+		msleep(S3FWRN5_EN_WAIT_TIME);
 	}
 
 	phy->irq_skip = true;
-- 
1.9.1


^ permalink raw reply related	[relevance 90%]

* [PATCH v3 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks
@ 2020-11-30 12:03 61% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-30 12:03 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Extract the common phy blocks to reuse it.
The UART module will use the common blocks.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 Changes in v3:
   - move the phy_common object to s3fwrn.ko to avoid duplication.
   - include the header files to include everything which is used inside.
   - wrap the lines.

 Changes in v2:
   - remove the common function's definition in common header file.
   - make the common phy_common.c file to define the common function.
   - wrap the lines.
   - change the Header guard.
   - remove the unused common function.

 drivers/nfc/s3fwrn5/Makefile     |   2 +-
 drivers/nfc/s3fwrn5/i2c.c        | 117 +++++++++++++--------------------------
 drivers/nfc/s3fwrn5/phy_common.c |  63 +++++++++++++++++++++
 drivers/nfc/s3fwrn5/phy_common.h |  36 ++++++++++++
 4 files changed, 139 insertions(+), 79 deletions(-)
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.c
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.h

diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index d0ffa35..6b6f52d 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -3,7 +3,7 @@
 # Makefile for Samsung S3FWRN5 NFC driver
 #
 
-s3fwrn5-objs = core.o firmware.o nci.o
+s3fwrn5-objs = core.o firmware.o nci.o phy_common.o
 s3fwrn5_i2c-objs = i2c.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index 9a64eea..e1bdde1 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -15,75 +15,30 @@
 
 #include <net/nfc/nfc.h>
 
-#include "s3fwrn5.h"
+#include "phy_common.h"
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_EN_WAIT_TIME 20
-
 struct s3fwrn5_i2c_phy {
+	struct phy_common common;
 	struct i2c_client *i2c_dev;
-	struct nci_dev *ndev;
-
-	int gpio_en;
-	int gpio_fw_wake;
-
-	struct mutex mutex;
 
-	enum s3fwrn5_mode mode;
 	unsigned int irq_skip:1;
 };
 
-static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
-{
-	struct s3fwrn5_i2c_phy *phy = phy_id;
-
-	mutex_lock(&phy->mutex);
-	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME);
-	mutex_unlock(&phy->mutex);
-}
-
 static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
 {
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
-	if (phy->mode == mode)
+	if (s3fwrn5_phy_power_ctrl(&phy->common, mode) == false)
 		goto out;
 
-	phy->mode = mode;
-
-	gpio_set_value(phy->gpio_en, 1);
-	gpio_set_value(phy->gpio_fw_wake, 0);
-	if (mode == S3FWRN5_MODE_FW)
-		gpio_set_value(phy->gpio_fw_wake, 1);
-
-	if (mode != S3FWRN5_MODE_COLD) {
-		msleep(S3FWRN5_EN_WAIT_TIME);
-		gpio_set_value(phy->gpio_en, 0);
-		msleep(S3FWRN5_EN_WAIT_TIME);
-	}
-
 	phy->irq_skip = true;
 
 out:
-	mutex_unlock(&phy->mutex);
-}
-
-static enum s3fwrn5_mode s3fwrn5_i2c_get_mode(void *phy_id)
-{
-	struct s3fwrn5_i2c_phy *phy = phy_id;
-	enum s3fwrn5_mode mode;
-
-	mutex_lock(&phy->mutex);
-
-	mode = phy->mode;
-
-	mutex_unlock(&phy->mutex);
-
-	return mode;
+	mutex_unlock(&phy->common.mutex);
 }
 
 static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
@@ -91,7 +46,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 	int ret;
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
 	phy->irq_skip = false;
 
@@ -102,7 +57,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 		ret  = i2c_master_send(phy->i2c_dev, skb->data, skb->len);
 	}
 
-	mutex_unlock(&phy->mutex);
+	mutex_unlock(&phy->common.mutex);
 
 	if (ret < 0)
 		return ret;
@@ -114,9 +69,9 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 }
 
 static const struct s3fwrn5_phy_ops i2c_phy_ops = {
-	.set_wake = s3fwrn5_i2c_set_wake,
+	.set_wake = s3fwrn5_phy_set_wake,
 	.set_mode = s3fwrn5_i2c_set_mode,
-	.get_mode = s3fwrn5_i2c_get_mode,
+	.get_mode = s3fwrn5_phy_get_mode,
 	.write = s3fwrn5_i2c_write,
 };
 
@@ -128,7 +83,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	char hdr[4];
 	int ret;
 
-	hdr_size = (phy->mode == S3FWRN5_MODE_NCI) ?
+	hdr_size = (phy->common.mode == S3FWRN5_MODE_NCI) ?
 		NCI_CTRL_HDR_SIZE : S3FWRN5_FW_HDR_SIZE;
 	ret = i2c_master_recv(phy->i2c_dev, hdr, hdr_size);
 	if (ret < 0)
@@ -137,7 +92,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	if (ret < hdr_size)
 		return -EBADMSG;
 
-	data_len = (phy->mode == S3FWRN5_MODE_NCI) ?
+	data_len = (phy->common.mode == S3FWRN5_MODE_NCI) ?
 		((struct nci_ctrl_hdr *)hdr)->plen :
 		((struct s3fwrn5_fw_header *)hdr)->len;
 
@@ -157,24 +112,24 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	}
 
 out:
-	return s3fwrn5_recv_frame(phy->ndev, skb, phy->mode);
+	return s3fwrn5_recv_frame(phy->common.ndev, skb, phy->common.mode);
 }
 
 static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
 {
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 
-	if (!phy || !phy->ndev) {
+	if (!phy || !phy->common.ndev) {
 		WARN_ON_ONCE(1);
 		return IRQ_NONE;
 	}
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
 	if (phy->irq_skip)
 		goto out;
 
-	switch (phy->mode) {
+	switch (phy->common.mode) {
 	case S3FWRN5_MODE_NCI:
 	case S3FWRN5_MODE_FW:
 		s3fwrn5_i2c_read(phy);
@@ -184,7 +139,7 @@ static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
 	}
 
 out:
-	mutex_unlock(&phy->mutex);
+	mutex_unlock(&phy->common.mutex);
 
 	return IRQ_HANDLED;
 }
@@ -197,19 +152,23 @@ static int s3fwrn5_i2c_parse_dt(struct i2c_client *client)
 	if (!np)
 		return -ENODEV;
 
-	phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
-	if (!gpio_is_valid(phy->gpio_en)) {
+	phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_en)) {
 		/* Support also deprecated property */
-		phy->gpio_en = of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
-		if (!gpio_is_valid(phy->gpio_en))
+		phy->common.gpio_en = of_get_named_gpio(np,
+							"s3fwrn5,en-gpios",
+							0);
+		if (!gpio_is_valid(phy->common.gpio_en))
 			return -ENODEV;
 	}
 
-	phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
-	if (!gpio_is_valid(phy->gpio_fw_wake)) {
+	phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_fw_wake)) {
 		/* Support also deprecated property */
-		phy->gpio_fw_wake = of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
-		if (!gpio_is_valid(phy->gpio_fw_wake))
+		phy->common.gpio_fw_wake = of_get_named_gpio(np,
+							     "s3fwrn5,fw-gpios",
+							     0);
+		if (!gpio_is_valid(phy->common.gpio_fw_wake))
 			return -ENODEV;
 	}
 
@@ -226,8 +185,8 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (!phy)
 		return -ENOMEM;
 
-	mutex_init(&phy->mutex);
-	phy->mode = S3FWRN5_MODE_COLD;
+	mutex_init(&phy->common.mutex);
+	phy->common.mode = S3FWRN5_MODE_COLD;
 	phy->irq_skip = true;
 
 	phy->i2c_dev = client;
@@ -237,17 +196,19 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
-		GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
+	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->common.gpio_en,
+				    GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
 	if (ret < 0)
 		return ret;
 
-	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw_wake,
-		GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
+	ret = devm_gpio_request_one(&phy->i2c_dev->dev,
+				    phy->common.gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
 	if (ret < 0)
 		return ret;
 
-	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
+	ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->i2c_dev->dev,
+			    &i2c_phy_ops);
 	if (ret < 0)
 		return ret;
 
@@ -255,7 +216,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 		s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 		S3FWRN5_I2C_DRIVER_NAME, phy);
 	if (ret)
-		s3fwrn5_remove(phy->ndev);
+		s3fwrn5_remove(phy->common.ndev);
 
 	return ret;
 }
@@ -264,7 +225,7 @@ static int s3fwrn5_i2c_remove(struct i2c_client *client)
 {
 	struct s3fwrn5_i2c_phy *phy = i2c_get_clientdata(client);
 
-	s3fwrn5_remove(phy->ndev);
+	s3fwrn5_remove(phy->common.ndev);
 
 	return 0;
 }
diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
new file mode 100644
index 0000000..5cad1f4
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Link Layer for Samsung S3FWRN5 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electrnoics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include "phy_common.h"
+
+void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
+{
+	struct phy_common *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+	gpio_set_value(phy->gpio_fw_wake, wake);
+	msleep(S3FWRN5_EN_WAIT_TIME);
+	mutex_unlock(&phy->mutex);
+}
+EXPORT_SYMBOL(s3fwrn5_phy_set_wake);
+
+bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
+{
+	if (phy->mode == mode)
+		return false;
+
+	phy->mode = mode;
+
+	gpio_set_value(phy->gpio_en, 1);
+	gpio_set_value(phy->gpio_fw_wake, 0);
+	if (mode == S3FWRN5_MODE_FW)
+		gpio_set_value(phy->gpio_fw_wake, 1);
+
+	if (mode != S3FWRN5_MODE_COLD) {
+		msleep(S3FWRN5_EN_WAIT_TIME);
+		gpio_set_value(phy->gpio_en, 0);
+		msleep(S3FWRN5_EN_WAIT_TIME);
+	}
+
+	return true;
+}
+EXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
+
+enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
+{
+	struct phy_common *phy = phy_id;
+	enum s3fwrn5_mode mode;
+
+	mutex_lock(&phy->mutex);
+
+	mode = phy->mode;
+
+	mutex_unlock(&phy->mutex);
+
+	return mode;
+}
+EXPORT_SYMBOL(s3fwrn5_phy_get_mode);
diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
new file mode 100644
index 0000000..b98531d
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/phy_common.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Link Layer for Samsung S3FWRN5 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electrnoics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#ifndef __NFC_S3FWRN5_PHY_COMMON_H
+#define __NFC_S3FWRN5_PHY_COMMON_H
+
+#include <linux/mutex.h>
+#include <net/nfc/nci_core.h>
+
+#include "s3fwrn5.h"
+
+#define S3FWRN5_EN_WAIT_TIME 20
+
+struct phy_common {
+	struct nci_dev *ndev;
+
+	int gpio_en;
+	int gpio_fw_wake;
+
+	struct mutex mutex;
+
+	enum s3fwrn5_mode mode;
+};
+
+void s3fwrn5_phy_set_wake(void *phy_id, bool wake);
+bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode);
+enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id);
+
+#endif /* __NFC_S3FWRN5_PHY_COMMON_H */
-- 
1.9.1


^ permalink raw reply related	[relevance 61%]

* [PATCH v2 net-next 4/4] net: nfc: s3fwrn5: Support a UART interface
@ 2020-11-30 12:05 68% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-11-30 12:05 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 uses NCI protocol and supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---

 Changes in v2:
   - remove the kfree(phy) because of duplicated free.
   - use the phy_common blocks.
   - wrap lines properly.

 drivers/nfc/s3fwrn5/Kconfig      |  12 +++
 drivers/nfc/s3fwrn5/Makefile     |   2 +
 drivers/nfc/s3fwrn5/phy_common.c |  12 +++
 drivers/nfc/s3fwrn5/phy_common.h |   1 +
 drivers/nfc/s3fwrn5/uart.c       | 197 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 224 insertions(+)
 create mode 100644 drivers/nfc/s3fwrn5/uart.c

diff --git a/drivers/nfc/s3fwrn5/Kconfig b/drivers/nfc/s3fwrn5/Kconfig
index 3f8b6da..8a6b1a7 100644
--- a/drivers/nfc/s3fwrn5/Kconfig
+++ b/drivers/nfc/s3fwrn5/Kconfig
@@ -20,3 +20,15 @@ config NFC_S3FWRN5_I2C
 	  To compile this driver as a module, choose m here. The module will
 	  be called s3fwrn5_i2c.ko.
 	  Say N if unsure.
+
+config NFC_S3FWRN82_UART
+        tristate "Samsung S3FWRN82 UART support"
+        depends on NFC_NCI && SERIAL_DEV_BUS
+        select NFC_S3FWRN5
+        help
+          This module adds support for a UART interface to the S3FWRN82 chip.
+          Select this if your platform is using the UART bus.
+
+          To compile this driver as a module, choose m here. The module will
+          be called s3fwrn82_uart.ko.
+          Say N if unsure.
diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index 6b6f52d..7da827a 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -5,6 +5,8 @@
 
 s3fwrn5-objs = core.o firmware.o nci.o phy_common.o
 s3fwrn5_i2c-objs = i2c.o
+s3fwrn82_uart-objs = uart.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
 obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
+obj-$(CONFIG_NFC_S3FWRN82_UART) += s3fwrn82_uart.o
diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
index 5cad1f4..497b02b 100644
--- a/drivers/nfc/s3fwrn5/phy_common.c
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -47,6 +47,18 @@ bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
 }
 EXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
 
+void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode)
+{
+	struct phy_common *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+
+	s3fwrn5_phy_power_ctrl(phy, mode);
+
+	mutex_unlock(&phy->mutex);
+}
+EXPORT_SYMBOL(s3fwrn5_phy_set_mode);
+
 enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
 {
 	struct phy_common *phy = phy_id;
diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
index b98531d..99749c9 100644
--- a/drivers/nfc/s3fwrn5/phy_common.h
+++ b/drivers/nfc/s3fwrn5/phy_common.h
@@ -31,6 +31,7 @@ struct phy_common {
 
 void s3fwrn5_phy_set_wake(void *phy_id, bool wake);
 bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode);
+void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode);
 enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id);
 
 #endif /* __NFC_S3FWRN5_PHY_COMMON_H */
diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
new file mode 100644
index 0000000..f5ac017
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/uart.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UART Link Layer for S3FWRN82 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electronics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/serdev.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include "phy_common.h"
+
+#define S3FWRN82_NCI_HEADER 3
+#define S3FWRN82_NCI_IDX 2
+#define NCI_SKB_BUFF_LEN 258
+
+struct s3fwrn82_uart_phy {
+	struct phy_common common;
+	struct serdev_device *ser_dev;
+	struct sk_buff *recv_skb;
+};
+
+static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+	int err;
+
+	err = serdev_device_write(phy->ser_dev,
+				  out->data, out->len,
+				  MAX_SCHEDULE_TIMEOUT);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static const struct s3fwrn5_phy_ops uart_phy_ops = {
+	.set_wake = s3fwrn5_phy_set_wake,
+	.set_mode = s3fwrn5_phy_set_mode,
+	.get_mode = s3fwrn5_phy_get_mode,
+	.write = s3fwrn82_uart_write,
+};
+
+static int s3fwrn82_uart_read(struct serdev_device *serdev,
+			      const unsigned char *data,
+			      size_t count)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	size_t i;
+
+	for (i = 0; i < count; i++) {
+		skb_put_u8(phy->recv_skb, *data++);
+
+		if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
+			continue;
+
+		if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
+				< phy->recv_skb->data[S3FWRN82_NCI_IDX])
+			continue;
+
+		s3fwrn5_recv_frame(phy->common.ndev, phy->recv_skb,
+				   phy->common.mode);
+		phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+		if (!phy->recv_skb)
+			return 0;
+	}
+
+	return i;
+}
+
+static const struct serdev_device_ops s3fwrn82_serdev_ops = {
+	.receive_buf = s3fwrn82_uart_read,
+	.write_wakeup = serdev_device_write_wakeup,
+};
+
+static const struct of_device_id s3fwrn82_uart_of_match[] = {
+	{ .compatible = "samsung,s3fwrn82", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
+
+static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	struct device_node *np = serdev->dev.of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_en))
+		return -ENODEV;
+
+	phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_fw_wake))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int s3fwrn82_uart_probe(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy;
+	int ret = -ENOMEM;
+
+	phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		goto err_exit;
+
+	phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+	if (!phy->recv_skb)
+		goto err_free;
+
+	mutex_init(&phy->common.mutex);
+	phy->common.mode = S3FWRN5_MODE_COLD;
+
+	phy->ser_dev = serdev;
+	serdev_device_set_drvdata(serdev, phy);
+	serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
+	ret = serdev_device_open(serdev);
+	if (ret) {
+		dev_err(&serdev->dev, "Unable to open device\n");
+		goto err_skb;
+	}
+
+	ret = serdev_device_set_baudrate(serdev, 115200);
+	if (ret != 115200) {
+		ret = -EINVAL;
+		goto err_serdev;
+	}
+
+	serdev_device_set_flow_control(serdev, false);
+
+	ret = s3fwrn82_uart_parse_dt(serdev);
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev, phy->common.gpio_en,
+				    GPIOF_OUT_INIT_HIGH, "s3fwrn82_en");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev,
+				    phy->common.gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW, "s3fwrn82_fw_wake");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->ser_dev->dev,
+			    &uart_phy_ops);
+	if (ret < 0)
+		goto err_serdev;
+
+	return ret;
+
+err_serdev:
+	serdev_device_close(serdev);
+err_skb:
+	kfree_skb(phy->recv_skb);
+err_free:
+err_exit:
+	return ret;
+}
+
+static void s3fwrn82_uart_remove(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+
+	s3fwrn5_remove(phy->common.ndev);
+	serdev_device_close(serdev);
+	kfree_skb(phy->recv_skb);
+}
+
+static struct serdev_device_driver s3fwrn82_uart_driver = {
+	.probe = s3fwrn82_uart_probe,
+	.remove = s3fwrn82_uart_remove,
+	.driver = {
+		.name = "s3fwrn82_uart",
+		.of_match_table = of_match_ptr(s3fwrn82_uart_of_match),
+	},
+};
+
+module_serdev_device_driver(s3fwrn82_uart_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UART driver for Samsung NFC");
+MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
-- 
1.9.1


^ permalink raw reply related	[relevance 68%]

* [PATCH v4 net-next 0/4] nfc: s3fwrn5: Support a UART interface
@ 2020-12-01 13:50 86% Bongsu Jeon
  2020-12-01 13:50 90% ` [PATCH v4 net-next 1/4] dt-bindings: net: " Bongsu Jeon
                   ` (3 more replies)
  0 siblings, 4 replies; 79+ results
From: Bongsu Jeon @ 2020-12-01 13:50 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

S3FWRN82 is the Samsung's NFC chip that supports the UART communication.
Before adding the UART driver module, I did refactoring the s3fwrn5_i2c module 
to reuse the common blocks.

1/4 is the dt bindings for the RN82 UART interface.
2/4..3/4 are refactoring the s3fwrn5_i2c module.
4/4 is the UART driver module implementation.

ChangeLog:
 v4:
   1/4
    - change 'oneOf' to 'items'.
    - fix the indentation.
   2/4
    - add the ACK tag.
   4/4
    - remove the of_match_ptr macro.
 v3:
   3/4
    - move the phy_common object to s3fwrn.ko to avoid duplication.
    - include the header files to include everything which is used inside.
    - wrap the lines.
   4/4
    - remove the kfree(phy) because of duplicated free.
    - use the phy_common blocks.
    - wrap lines properly.
 v2:
   1/4
    - change the compatible name.
    - change the const to enum for compatible.
    - change the node name to nfc.
   3/4
    - remove the common function's definition in common header file.
    - make the common phy_common.c file to define the common function.
    - wrap the lines.
    - change the Header guard.
    - remove the unused common function.


Bongsu Jeon (4):
  dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  nfc: s3fwrn5: reduce the EN_WAIT_TIME
  nfc: s3fwrn5: extract the common phy blocks
  nfc: s3fwrn5: Support a UART interface

 .../bindings/net/nfc/samsung,s3fwrn5.yaml          |  32 +++-
 drivers/nfc/s3fwrn5/Kconfig                        |  12 ++
 drivers/nfc/s3fwrn5/Makefile                       |   4 +-
 drivers/nfc/s3fwrn5/i2c.c                          | 117 ++++--------
 drivers/nfc/s3fwrn5/phy_common.c                   |  75 ++++++++
 drivers/nfc/s3fwrn5/phy_common.h                   |  37 ++++
 drivers/nfc/s3fwrn5/uart.c                         | 196 +++++++++++++++++++++
 7 files changed, 391 insertions(+), 82 deletions(-)
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.c
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.h
 create mode 100644 drivers/nfc/s3fwrn5/uart.c

-- 
1.9.1


^ permalink raw reply	[relevance 86%]

* [PATCH v4 net-next 1/4] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  2020-12-01 13:50 86% [PATCH v4 net-next 0/4] " Bongsu Jeon
@ 2020-12-01 13:50 90% ` Bongsu Jeon
  2020-12-01 13:50 90% ` [PATCH v4 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-01 13:50 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 .../bindings/net/nfc/samsung,s3fwrn5.yaml          | 32 ++++++++++++++++++++--
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
index cb0b8a5..cc5f9a1 100644
--- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
@@ -12,7 +12,10 @@ maintainers:
 
 properties:
   compatible:
-    const: samsung,s3fwrn5-i2c
+    items:
+      - enum:
+          - samsung,s3fwrn5-i2c
+          - samsung,s3fwrn82
 
   en-gpios:
     maxItems: 1
@@ -47,10 +50,19 @@ additionalProperties: false
 required:
   - compatible
   - en-gpios
-  - interrupts
-  - reg
   - wake-gpios
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s3fwrn5-i2c
+    then:
+      required:
+        - interrupts
+        - reg
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
@@ -71,3 +83,17 @@ examples:
             wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
         };
     };
+  # UART example on Raspberry Pi
+  - |
+    uart0 {
+        status = "okay";
+
+        nfc {
+            compatible = "samsung,s3fwrn82";
+
+            en-gpios = <&gpio 20 0>;
+            wake-gpios = <&gpio 16 0>;
+
+            status = "okay";
+        };
+    };
-- 
1.9.1


^ permalink raw reply related	[relevance 90%]

* [PATCH v4 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME
  2020-12-01 13:50 86% [PATCH v4 net-next 0/4] " Bongsu Jeon
  2020-12-01 13:50 90% ` [PATCH v4 net-next 1/4] dt-bindings: net: " Bongsu Jeon
@ 2020-12-01 13:50 90% ` Bongsu Jeon
  2020-12-01 13:50 62% ` [PATCH v4 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
  2020-12-01 13:50 68% ` [PATCH v4 net-next 4/4] nfc: s3fwrn5: Support a UART interface Bongsu Jeon
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-01 13:50 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

The delay of 20ms is enough to enable and
wake up the Samsung's nfc chip.

Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/i2c.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index ae26594..9a64eea 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -19,7 +19,7 @@
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_EN_WAIT_TIME 150
+#define S3FWRN5_EN_WAIT_TIME 20
 
 struct s3fwrn5_i2c_phy {
 	struct i2c_client *i2c_dev;
@@ -40,7 +40,7 @@ static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
 
 	mutex_lock(&phy->mutex);
 	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME/2);
+	msleep(S3FWRN5_EN_WAIT_TIME);
 	mutex_unlock(&phy->mutex);
 }
 
@@ -63,7 +63,7 @@ static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
 	if (mode != S3FWRN5_MODE_COLD) {
 		msleep(S3FWRN5_EN_WAIT_TIME);
 		gpio_set_value(phy->gpio_en, 0);
-		msleep(S3FWRN5_EN_WAIT_TIME/2);
+		msleep(S3FWRN5_EN_WAIT_TIME);
 	}
 
 	phy->irq_skip = true;
-- 
1.9.1


^ permalink raw reply related	[relevance 90%]

* [PATCH v4 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks
  2020-12-01 13:50 86% [PATCH v4 net-next 0/4] " Bongsu Jeon
  2020-12-01 13:50 90% ` [PATCH v4 net-next 1/4] dt-bindings: net: " Bongsu Jeon
  2020-12-01 13:50 90% ` [PATCH v4 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
@ 2020-12-01 13:50 62% ` Bongsu Jeon
  2020-12-01 13:50 68% ` [PATCH v4 net-next 4/4] nfc: s3fwrn5: Support a UART interface Bongsu Jeon
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-01 13:50 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Extract the common phy blocks to reuse it.
The UART module will use the common blocks.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/Makefile     |   2 +-
 drivers/nfc/s3fwrn5/i2c.c        | 117 +++++++++++++--------------------------
 drivers/nfc/s3fwrn5/phy_common.c |  63 +++++++++++++++++++++
 drivers/nfc/s3fwrn5/phy_common.h |  36 ++++++++++++
 4 files changed, 139 insertions(+), 79 deletions(-)
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.c
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.h

diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index d0ffa35..6b6f52d 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -3,7 +3,7 @@
 # Makefile for Samsung S3FWRN5 NFC driver
 #
 
-s3fwrn5-objs = core.o firmware.o nci.o
+s3fwrn5-objs = core.o firmware.o nci.o phy_common.o
 s3fwrn5_i2c-objs = i2c.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index 9a64eea..e1bdde1 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -15,75 +15,30 @@
 
 #include <net/nfc/nfc.h>
 
-#include "s3fwrn5.h"
+#include "phy_common.h"
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_EN_WAIT_TIME 20
-
 struct s3fwrn5_i2c_phy {
+	struct phy_common common;
 	struct i2c_client *i2c_dev;
-	struct nci_dev *ndev;
-
-	int gpio_en;
-	int gpio_fw_wake;
-
-	struct mutex mutex;
 
-	enum s3fwrn5_mode mode;
 	unsigned int irq_skip:1;
 };
 
-static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
-{
-	struct s3fwrn5_i2c_phy *phy = phy_id;
-
-	mutex_lock(&phy->mutex);
-	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME);
-	mutex_unlock(&phy->mutex);
-}
-
 static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
 {
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
-	if (phy->mode == mode)
+	if (s3fwrn5_phy_power_ctrl(&phy->common, mode) == false)
 		goto out;
 
-	phy->mode = mode;
-
-	gpio_set_value(phy->gpio_en, 1);
-	gpio_set_value(phy->gpio_fw_wake, 0);
-	if (mode == S3FWRN5_MODE_FW)
-		gpio_set_value(phy->gpio_fw_wake, 1);
-
-	if (mode != S3FWRN5_MODE_COLD) {
-		msleep(S3FWRN5_EN_WAIT_TIME);
-		gpio_set_value(phy->gpio_en, 0);
-		msleep(S3FWRN5_EN_WAIT_TIME);
-	}
-
 	phy->irq_skip = true;
 
 out:
-	mutex_unlock(&phy->mutex);
-}
-
-static enum s3fwrn5_mode s3fwrn5_i2c_get_mode(void *phy_id)
-{
-	struct s3fwrn5_i2c_phy *phy = phy_id;
-	enum s3fwrn5_mode mode;
-
-	mutex_lock(&phy->mutex);
-
-	mode = phy->mode;
-
-	mutex_unlock(&phy->mutex);
-
-	return mode;
+	mutex_unlock(&phy->common.mutex);
 }
 
 static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
@@ -91,7 +46,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 	int ret;
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
 	phy->irq_skip = false;
 
@@ -102,7 +57,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 		ret  = i2c_master_send(phy->i2c_dev, skb->data, skb->len);
 	}
 
-	mutex_unlock(&phy->mutex);
+	mutex_unlock(&phy->common.mutex);
 
 	if (ret < 0)
 		return ret;
@@ -114,9 +69,9 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 }
 
 static const struct s3fwrn5_phy_ops i2c_phy_ops = {
-	.set_wake = s3fwrn5_i2c_set_wake,
+	.set_wake = s3fwrn5_phy_set_wake,
 	.set_mode = s3fwrn5_i2c_set_mode,
-	.get_mode = s3fwrn5_i2c_get_mode,
+	.get_mode = s3fwrn5_phy_get_mode,
 	.write = s3fwrn5_i2c_write,
 };
 
@@ -128,7 +83,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	char hdr[4];
 	int ret;
 
-	hdr_size = (phy->mode == S3FWRN5_MODE_NCI) ?
+	hdr_size = (phy->common.mode == S3FWRN5_MODE_NCI) ?
 		NCI_CTRL_HDR_SIZE : S3FWRN5_FW_HDR_SIZE;
 	ret = i2c_master_recv(phy->i2c_dev, hdr, hdr_size);
 	if (ret < 0)
@@ -137,7 +92,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	if (ret < hdr_size)
 		return -EBADMSG;
 
-	data_len = (phy->mode == S3FWRN5_MODE_NCI) ?
+	data_len = (phy->common.mode == S3FWRN5_MODE_NCI) ?
 		((struct nci_ctrl_hdr *)hdr)->plen :
 		((struct s3fwrn5_fw_header *)hdr)->len;
 
@@ -157,24 +112,24 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	}
 
 out:
-	return s3fwrn5_recv_frame(phy->ndev, skb, phy->mode);
+	return s3fwrn5_recv_frame(phy->common.ndev, skb, phy->common.mode);
 }
 
 static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
 {
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 
-	if (!phy || !phy->ndev) {
+	if (!phy || !phy->common.ndev) {
 		WARN_ON_ONCE(1);
 		return IRQ_NONE;
 	}
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
 	if (phy->irq_skip)
 		goto out;
 
-	switch (phy->mode) {
+	switch (phy->common.mode) {
 	case S3FWRN5_MODE_NCI:
 	case S3FWRN5_MODE_FW:
 		s3fwrn5_i2c_read(phy);
@@ -184,7 +139,7 @@ static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
 	}
 
 out:
-	mutex_unlock(&phy->mutex);
+	mutex_unlock(&phy->common.mutex);
 
 	return IRQ_HANDLED;
 }
@@ -197,19 +152,23 @@ static int s3fwrn5_i2c_parse_dt(struct i2c_client *client)
 	if (!np)
 		return -ENODEV;
 
-	phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
-	if (!gpio_is_valid(phy->gpio_en)) {
+	phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_en)) {
 		/* Support also deprecated property */
-		phy->gpio_en = of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
-		if (!gpio_is_valid(phy->gpio_en))
+		phy->common.gpio_en = of_get_named_gpio(np,
+							"s3fwrn5,en-gpios",
+							0);
+		if (!gpio_is_valid(phy->common.gpio_en))
 			return -ENODEV;
 	}
 
-	phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
-	if (!gpio_is_valid(phy->gpio_fw_wake)) {
+	phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_fw_wake)) {
 		/* Support also deprecated property */
-		phy->gpio_fw_wake = of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
-		if (!gpio_is_valid(phy->gpio_fw_wake))
+		phy->common.gpio_fw_wake = of_get_named_gpio(np,
+							     "s3fwrn5,fw-gpios",
+							     0);
+		if (!gpio_is_valid(phy->common.gpio_fw_wake))
 			return -ENODEV;
 	}
 
@@ -226,8 +185,8 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (!phy)
 		return -ENOMEM;
 
-	mutex_init(&phy->mutex);
-	phy->mode = S3FWRN5_MODE_COLD;
+	mutex_init(&phy->common.mutex);
+	phy->common.mode = S3FWRN5_MODE_COLD;
 	phy->irq_skip = true;
 
 	phy->i2c_dev = client;
@@ -237,17 +196,19 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
-		GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
+	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->common.gpio_en,
+				    GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
 	if (ret < 0)
 		return ret;
 
-	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw_wake,
-		GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
+	ret = devm_gpio_request_one(&phy->i2c_dev->dev,
+				    phy->common.gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
 	if (ret < 0)
 		return ret;
 
-	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
+	ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->i2c_dev->dev,
+			    &i2c_phy_ops);
 	if (ret < 0)
 		return ret;
 
@@ -255,7 +216,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 		s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 		S3FWRN5_I2C_DRIVER_NAME, phy);
 	if (ret)
-		s3fwrn5_remove(phy->ndev);
+		s3fwrn5_remove(phy->common.ndev);
 
 	return ret;
 }
@@ -264,7 +225,7 @@ static int s3fwrn5_i2c_remove(struct i2c_client *client)
 {
 	struct s3fwrn5_i2c_phy *phy = i2c_get_clientdata(client);
 
-	s3fwrn5_remove(phy->ndev);
+	s3fwrn5_remove(phy->common.ndev);
 
 	return 0;
 }
diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
new file mode 100644
index 0000000..5cad1f4
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Link Layer for Samsung S3FWRN5 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electrnoics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include "phy_common.h"
+
+void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
+{
+	struct phy_common *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+	gpio_set_value(phy->gpio_fw_wake, wake);
+	msleep(S3FWRN5_EN_WAIT_TIME);
+	mutex_unlock(&phy->mutex);
+}
+EXPORT_SYMBOL(s3fwrn5_phy_set_wake);
+
+bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
+{
+	if (phy->mode == mode)
+		return false;
+
+	phy->mode = mode;
+
+	gpio_set_value(phy->gpio_en, 1);
+	gpio_set_value(phy->gpio_fw_wake, 0);
+	if (mode == S3FWRN5_MODE_FW)
+		gpio_set_value(phy->gpio_fw_wake, 1);
+
+	if (mode != S3FWRN5_MODE_COLD) {
+		msleep(S3FWRN5_EN_WAIT_TIME);
+		gpio_set_value(phy->gpio_en, 0);
+		msleep(S3FWRN5_EN_WAIT_TIME);
+	}
+
+	return true;
+}
+EXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
+
+enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
+{
+	struct phy_common *phy = phy_id;
+	enum s3fwrn5_mode mode;
+
+	mutex_lock(&phy->mutex);
+
+	mode = phy->mode;
+
+	mutex_unlock(&phy->mutex);
+
+	return mode;
+}
+EXPORT_SYMBOL(s3fwrn5_phy_get_mode);
diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
new file mode 100644
index 0000000..b98531d
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/phy_common.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Link Layer for Samsung S3FWRN5 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electrnoics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#ifndef __NFC_S3FWRN5_PHY_COMMON_H
+#define __NFC_S3FWRN5_PHY_COMMON_H
+
+#include <linux/mutex.h>
+#include <net/nfc/nci_core.h>
+
+#include "s3fwrn5.h"
+
+#define S3FWRN5_EN_WAIT_TIME 20
+
+struct phy_common {
+	struct nci_dev *ndev;
+
+	int gpio_en;
+	int gpio_fw_wake;
+
+	struct mutex mutex;
+
+	enum s3fwrn5_mode mode;
+};
+
+void s3fwrn5_phy_set_wake(void *phy_id, bool wake);
+bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode);
+enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id);
+
+#endif /* __NFC_S3FWRN5_PHY_COMMON_H */
-- 
1.9.1


^ permalink raw reply related	[relevance 62%]

* [PATCH v4 net-next 4/4] nfc: s3fwrn5: Support a UART interface
  2020-12-01 13:50 86% [PATCH v4 net-next 0/4] " Bongsu Jeon
                   ` (2 preceding siblings ...)
  2020-12-01 13:50 62% ` [PATCH v4 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
@ 2020-12-01 13:50 68% ` Bongsu Jeon
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-01 13:50 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 uses NCI protocol and supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/Kconfig      |  12 +++
 drivers/nfc/s3fwrn5/Makefile     |   2 +
 drivers/nfc/s3fwrn5/phy_common.c |  12 +++
 drivers/nfc/s3fwrn5/phy_common.h |   1 +
 drivers/nfc/s3fwrn5/uart.c       | 196 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 223 insertions(+)
 create mode 100644 drivers/nfc/s3fwrn5/uart.c

diff --git a/drivers/nfc/s3fwrn5/Kconfig b/drivers/nfc/s3fwrn5/Kconfig
index 3f8b6da..8a6b1a7 100644
--- a/drivers/nfc/s3fwrn5/Kconfig
+++ b/drivers/nfc/s3fwrn5/Kconfig
@@ -20,3 +20,15 @@ config NFC_S3FWRN5_I2C
 	  To compile this driver as a module, choose m here. The module will
 	  be called s3fwrn5_i2c.ko.
 	  Say N if unsure.
+
+config NFC_S3FWRN82_UART
+        tristate "Samsung S3FWRN82 UART support"
+        depends on NFC_NCI && SERIAL_DEV_BUS
+        select NFC_S3FWRN5
+        help
+          This module adds support for a UART interface to the S3FWRN82 chip.
+          Select this if your platform is using the UART bus.
+
+          To compile this driver as a module, choose m here. The module will
+          be called s3fwrn82_uart.ko.
+          Say N if unsure.
diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index 6b6f52d..7da827a 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -5,6 +5,8 @@
 
 s3fwrn5-objs = core.o firmware.o nci.o phy_common.o
 s3fwrn5_i2c-objs = i2c.o
+s3fwrn82_uart-objs = uart.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
 obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
+obj-$(CONFIG_NFC_S3FWRN82_UART) += s3fwrn82_uart.o
diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
index 5cad1f4..497b02b 100644
--- a/drivers/nfc/s3fwrn5/phy_common.c
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -47,6 +47,18 @@ bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
 }
 EXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
 
+void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode)
+{
+	struct phy_common *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+
+	s3fwrn5_phy_power_ctrl(phy, mode);
+
+	mutex_unlock(&phy->mutex);
+}
+EXPORT_SYMBOL(s3fwrn5_phy_set_mode);
+
 enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
 {
 	struct phy_common *phy = phy_id;
diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
index b98531d..99749c9 100644
--- a/drivers/nfc/s3fwrn5/phy_common.h
+++ b/drivers/nfc/s3fwrn5/phy_common.h
@@ -31,6 +31,7 @@ struct phy_common {
 
 void s3fwrn5_phy_set_wake(void *phy_id, bool wake);
 bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode);
+void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode);
 enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id);
 
 #endif /* __NFC_S3FWRN5_PHY_COMMON_H */
diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
new file mode 100644
index 0000000..82ea35d
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/uart.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UART Link Layer for S3FWRN82 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electronics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/serdev.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include "phy_common.h"
+
+#define S3FWRN82_NCI_HEADER 3
+#define S3FWRN82_NCI_IDX 2
+#define NCI_SKB_BUFF_LEN 258
+
+struct s3fwrn82_uart_phy {
+	struct phy_common common;
+	struct serdev_device *ser_dev;
+	struct sk_buff *recv_skb;
+};
+
+static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+	int err;
+
+	err = serdev_device_write(phy->ser_dev,
+				  out->data, out->len,
+				  MAX_SCHEDULE_TIMEOUT);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static const struct s3fwrn5_phy_ops uart_phy_ops = {
+	.set_wake = s3fwrn5_phy_set_wake,
+	.set_mode = s3fwrn5_phy_set_mode,
+	.get_mode = s3fwrn5_phy_get_mode,
+	.write = s3fwrn82_uart_write,
+};
+
+static int s3fwrn82_uart_read(struct serdev_device *serdev,
+			      const unsigned char *data,
+			      size_t count)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	size_t i;
+
+	for (i = 0; i < count; i++) {
+		skb_put_u8(phy->recv_skb, *data++);
+
+		if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
+			continue;
+
+		if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
+				< phy->recv_skb->data[S3FWRN82_NCI_IDX])
+			continue;
+
+		s3fwrn5_recv_frame(phy->common.ndev, phy->recv_skb,
+				   phy->common.mode);
+		phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+		if (!phy->recv_skb)
+			return 0;
+	}
+
+	return i;
+}
+
+static const struct serdev_device_ops s3fwrn82_serdev_ops = {
+	.receive_buf = s3fwrn82_uart_read,
+	.write_wakeup = serdev_device_write_wakeup,
+};
+
+static const struct of_device_id s3fwrn82_uart_of_match[] = {
+	{ .compatible = "samsung,s3fwrn82", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
+
+static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	struct device_node *np = serdev->dev.of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_en))
+		return -ENODEV;
+
+	phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_fw_wake))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int s3fwrn82_uart_probe(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy;
+	int ret = -ENOMEM;
+
+	phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		goto err_exit;
+
+	phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+	if (!phy->recv_skb)
+		goto err_exit;
+
+	mutex_init(&phy->common.mutex);
+	phy->common.mode = S3FWRN5_MODE_COLD;
+
+	phy->ser_dev = serdev;
+	serdev_device_set_drvdata(serdev, phy);
+	serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
+	ret = serdev_device_open(serdev);
+	if (ret) {
+		dev_err(&serdev->dev, "Unable to open device\n");
+		goto err_skb;
+	}
+
+	ret = serdev_device_set_baudrate(serdev, 115200);
+	if (ret != 115200) {
+		ret = -EINVAL;
+		goto err_serdev;
+	}
+
+	serdev_device_set_flow_control(serdev, false);
+
+	ret = s3fwrn82_uart_parse_dt(serdev);
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev, phy->common.gpio_en,
+				    GPIOF_OUT_INIT_HIGH, "s3fwrn82_en");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev,
+				    phy->common.gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW, "s3fwrn82_fw_wake");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->ser_dev->dev,
+			    &uart_phy_ops);
+	if (ret < 0)
+		goto err_serdev;
+
+	return ret;
+
+err_serdev:
+	serdev_device_close(serdev);
+err_skb:
+	kfree_skb(phy->recv_skb);
+err_exit:
+	return ret;
+}
+
+static void s3fwrn82_uart_remove(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+
+	s3fwrn5_remove(phy->common.ndev);
+	serdev_device_close(serdev);
+	kfree_skb(phy->recv_skb);
+}
+
+static struct serdev_device_driver s3fwrn82_uart_driver = {
+	.probe = s3fwrn82_uart_probe,
+	.remove = s3fwrn82_uart_remove,
+	.driver = {
+		.name = "s3fwrn82_uart",
+		.of_match_table = s3fwrn82_uart_of_match,
+	},
+};
+
+module_serdev_device_driver(s3fwrn82_uart_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UART driver for Samsung NFC");
+MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
-- 
1.9.1


^ permalink raw reply related	[relevance 68%]

* [PATCH v5 net-next 0/4] nfc: s3fwrn5: Support a UART interface
@ 2020-12-02 11:47 85% Bongsu Jeon
  2020-12-02 11:47 90% ` [PATCH v5 net-next 1/4] dt-bindings: net: " Bongsu Jeon
                   ` (3 more replies)
  0 siblings, 4 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 11:47 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

S3FWRN82 is the Samsung's NFC chip that supports the UART communication.
Before adding the UART driver module, I did refactoring the s3fwrn5_i2c module 
to reuse the common blocks.

1/4 is the dt bindings for the RN82 UART interface.
2/4..3/4 are refactoring the s3fwrn5_i2c module.
4/4 is the UART driver module implementation.

ChangeLog:
 v5:
   1/4
    - remove the 'items' of the compatible property.
    - change the GPIO flags.
 v4:
   1/4
    - change 'oneOf' to 'items'.
    - fix the indentation.
   2/4
    - add the ACK tag.
   4/4
    - remove the of_match_ptr macro.
 v3:
   3/4
    - move the phy_common object to s3fwrn.ko to avoid duplication.
    - include the header files to include everything which is used inside.
    - wrap the lines.
   4/4
    - remove the kfree(phy) because of duplicated free.
    - use the phy_common blocks.
    - wrap lines properly.
 v2:
   1/4
    - change the compatible name.
    - change the const to enum for compatible.
    - change the node name to nfc.
   3/4
    - remove the common function's definition in common header file.
    - make the common phy_common.c file to define the common function.
    - wrap the lines.
    - change the Header guard.
    - remove the unused common function.

Bongsu Jeon (4):
  dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  nfc: s3fwrn5: reduce the EN_WAIT_TIME
  nfc: s3fwrn5: extract the common phy blocks
  nfc: s3fwrn5: Support a UART interface

 .../bindings/net/nfc/samsung,s3fwrn5.yaml          |  31 +++-
 drivers/nfc/s3fwrn5/Kconfig                        |  12 ++
 drivers/nfc/s3fwrn5/Makefile                       |   4 +-
 drivers/nfc/s3fwrn5/i2c.c                          | 117 ++++--------
 drivers/nfc/s3fwrn5/phy_common.c                   |  75 ++++++++
 drivers/nfc/s3fwrn5/phy_common.h                   |  37 ++++
 drivers/nfc/s3fwrn5/uart.c                         | 196 +++++++++++++++++++++
 7 files changed, 390 insertions(+), 82 deletions(-)
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.c
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.h
 create mode 100644 drivers/nfc/s3fwrn5/uart.c

-- 
1.9.1


^ permalink raw reply	[relevance 85%]

* [PATCH v5 net-next 1/4] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  2020-12-02 11:47 85% [PATCH v5 net-next 0/4] " Bongsu Jeon
@ 2020-12-02 11:47 90% ` Bongsu Jeon
    2020-12-02 11:47 90% ` [PATCH v5 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-02 11:47 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 supports I2C and UART interface.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 .../bindings/net/nfc/samsung,s3fwrn5.yaml          | 31 +++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
index cb0b8a5..ca3904b 100644
--- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
@@ -12,7 +12,9 @@ maintainers:
 
 properties:
   compatible:
-    const: samsung,s3fwrn5-i2c
+    enum:
+      - samsung,s3fwrn5-i2c
+      - samsung,s3fwrn82
 
   en-gpios:
     maxItems: 1
@@ -47,10 +49,19 @@ additionalProperties: false
 required:
   - compatible
   - en-gpios
-  - interrupts
-  - reg
   - wake-gpios
 
+allOf:
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: samsung,s3fwrn5-i2c
+    then:
+      required:
+        - interrupts
+        - reg
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
@@ -71,3 +82,17 @@ examples:
             wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
         };
     };
+  # UART example on Raspberry Pi
+  - |
+    uart0 {
+        status = "okay";
+
+        nfc {
+            compatible = "samsung,s3fwrn82";
+
+            en-gpios = <&gpio 20 GPIO_ACTIVE_HIGH>;
+            wake-gpios = <&gpio 16 GPIO_ACTIVE_HIGH>;
+
+            status = "okay";
+        };
+    };
-- 
1.9.1


^ permalink raw reply related	[relevance 90%]

* [PATCH v5 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME
  2020-12-02 11:47 85% [PATCH v5 net-next 0/4] " Bongsu Jeon
  2020-12-02 11:47 90% ` [PATCH v5 net-next 1/4] dt-bindings: net: " Bongsu Jeon
@ 2020-12-02 11:47 90% ` Bongsu Jeon
  2020-12-02 11:47 62% ` [PATCH v5 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
  2020-12-02 11:47 68% ` [PATCH v5 net-next 4/4] nfc: s3fwrn5: Support a UART interface Bongsu Jeon
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 11:47 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

The delay of 20ms is enough to enable and
wake up the Samsung's nfc chip.

Acked-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/i2c.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index ae26594..9a64eea 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -19,7 +19,7 @@
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_EN_WAIT_TIME 150
+#define S3FWRN5_EN_WAIT_TIME 20
 
 struct s3fwrn5_i2c_phy {
 	struct i2c_client *i2c_dev;
@@ -40,7 +40,7 @@ static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
 
 	mutex_lock(&phy->mutex);
 	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME/2);
+	msleep(S3FWRN5_EN_WAIT_TIME);
 	mutex_unlock(&phy->mutex);
 }
 
@@ -63,7 +63,7 @@ static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
 	if (mode != S3FWRN5_MODE_COLD) {
 		msleep(S3FWRN5_EN_WAIT_TIME);
 		gpio_set_value(phy->gpio_en, 0);
-		msleep(S3FWRN5_EN_WAIT_TIME/2);
+		msleep(S3FWRN5_EN_WAIT_TIME);
 	}
 
 	phy->irq_skip = true;
-- 
1.9.1


^ permalink raw reply related	[relevance 90%]

* [PATCH v5 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks
  2020-12-02 11:47 85% [PATCH v5 net-next 0/4] " Bongsu Jeon
  2020-12-02 11:47 90% ` [PATCH v5 net-next 1/4] dt-bindings: net: " Bongsu Jeon
  2020-12-02 11:47 90% ` [PATCH v5 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
@ 2020-12-02 11:47 62% ` Bongsu Jeon
  2020-12-02 11:47 68% ` [PATCH v5 net-next 4/4] nfc: s3fwrn5: Support a UART interface Bongsu Jeon
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 11:47 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Extract the common phy blocks to reuse it.
The UART module will use the common blocks.

Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/Makefile     |   2 +-
 drivers/nfc/s3fwrn5/i2c.c        | 117 +++++++++++++--------------------------
 drivers/nfc/s3fwrn5/phy_common.c |  63 +++++++++++++++++++++
 drivers/nfc/s3fwrn5/phy_common.h |  36 ++++++++++++
 4 files changed, 139 insertions(+), 79 deletions(-)
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.c
 create mode 100644 drivers/nfc/s3fwrn5/phy_common.h

diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index d0ffa35..6b6f52d 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -3,7 +3,7 @@
 # Makefile for Samsung S3FWRN5 NFC driver
 #
 
-s3fwrn5-objs = core.o firmware.o nci.o
+s3fwrn5-objs = core.o firmware.o nci.o phy_common.o
 s3fwrn5_i2c-objs = i2c.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index 9a64eea..e1bdde1 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -15,75 +15,30 @@
 
 #include <net/nfc/nfc.h>
 
-#include "s3fwrn5.h"
+#include "phy_common.h"
 
 #define S3FWRN5_I2C_DRIVER_NAME "s3fwrn5_i2c"
 
-#define S3FWRN5_EN_WAIT_TIME 20
-
 struct s3fwrn5_i2c_phy {
+	struct phy_common common;
 	struct i2c_client *i2c_dev;
-	struct nci_dev *ndev;
-
-	int gpio_en;
-	int gpio_fw_wake;
-
-	struct mutex mutex;
 
-	enum s3fwrn5_mode mode;
 	unsigned int irq_skip:1;
 };
 
-static void s3fwrn5_i2c_set_wake(void *phy_id, bool wake)
-{
-	struct s3fwrn5_i2c_phy *phy = phy_id;
-
-	mutex_lock(&phy->mutex);
-	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME);
-	mutex_unlock(&phy->mutex);
-}
-
 static void s3fwrn5_i2c_set_mode(void *phy_id, enum s3fwrn5_mode mode)
 {
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
-	if (phy->mode == mode)
+	if (s3fwrn5_phy_power_ctrl(&phy->common, mode) == false)
 		goto out;
 
-	phy->mode = mode;
-
-	gpio_set_value(phy->gpio_en, 1);
-	gpio_set_value(phy->gpio_fw_wake, 0);
-	if (mode == S3FWRN5_MODE_FW)
-		gpio_set_value(phy->gpio_fw_wake, 1);
-
-	if (mode != S3FWRN5_MODE_COLD) {
-		msleep(S3FWRN5_EN_WAIT_TIME);
-		gpio_set_value(phy->gpio_en, 0);
-		msleep(S3FWRN5_EN_WAIT_TIME);
-	}
-
 	phy->irq_skip = true;
 
 out:
-	mutex_unlock(&phy->mutex);
-}
-
-static enum s3fwrn5_mode s3fwrn5_i2c_get_mode(void *phy_id)
-{
-	struct s3fwrn5_i2c_phy *phy = phy_id;
-	enum s3fwrn5_mode mode;
-
-	mutex_lock(&phy->mutex);
-
-	mode = phy->mode;
-
-	mutex_unlock(&phy->mutex);
-
-	return mode;
+	mutex_unlock(&phy->common.mutex);
 }
 
 static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
@@ -91,7 +46,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 	int ret;
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
 	phy->irq_skip = false;
 
@@ -102,7 +57,7 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 		ret  = i2c_master_send(phy->i2c_dev, skb->data, skb->len);
 	}
 
-	mutex_unlock(&phy->mutex);
+	mutex_unlock(&phy->common.mutex);
 
 	if (ret < 0)
 		return ret;
@@ -114,9 +69,9 @@ static int s3fwrn5_i2c_write(void *phy_id, struct sk_buff *skb)
 }
 
 static const struct s3fwrn5_phy_ops i2c_phy_ops = {
-	.set_wake = s3fwrn5_i2c_set_wake,
+	.set_wake = s3fwrn5_phy_set_wake,
 	.set_mode = s3fwrn5_i2c_set_mode,
-	.get_mode = s3fwrn5_i2c_get_mode,
+	.get_mode = s3fwrn5_phy_get_mode,
 	.write = s3fwrn5_i2c_write,
 };
 
@@ -128,7 +83,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	char hdr[4];
 	int ret;
 
-	hdr_size = (phy->mode == S3FWRN5_MODE_NCI) ?
+	hdr_size = (phy->common.mode == S3FWRN5_MODE_NCI) ?
 		NCI_CTRL_HDR_SIZE : S3FWRN5_FW_HDR_SIZE;
 	ret = i2c_master_recv(phy->i2c_dev, hdr, hdr_size);
 	if (ret < 0)
@@ -137,7 +92,7 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	if (ret < hdr_size)
 		return -EBADMSG;
 
-	data_len = (phy->mode == S3FWRN5_MODE_NCI) ?
+	data_len = (phy->common.mode == S3FWRN5_MODE_NCI) ?
 		((struct nci_ctrl_hdr *)hdr)->plen :
 		((struct s3fwrn5_fw_header *)hdr)->len;
 
@@ -157,24 +112,24 @@ static int s3fwrn5_i2c_read(struct s3fwrn5_i2c_phy *phy)
 	}
 
 out:
-	return s3fwrn5_recv_frame(phy->ndev, skb, phy->mode);
+	return s3fwrn5_recv_frame(phy->common.ndev, skb, phy->common.mode);
 }
 
 static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
 {
 	struct s3fwrn5_i2c_phy *phy = phy_id;
 
-	if (!phy || !phy->ndev) {
+	if (!phy || !phy->common.ndev) {
 		WARN_ON_ONCE(1);
 		return IRQ_NONE;
 	}
 
-	mutex_lock(&phy->mutex);
+	mutex_lock(&phy->common.mutex);
 
 	if (phy->irq_skip)
 		goto out;
 
-	switch (phy->mode) {
+	switch (phy->common.mode) {
 	case S3FWRN5_MODE_NCI:
 	case S3FWRN5_MODE_FW:
 		s3fwrn5_i2c_read(phy);
@@ -184,7 +139,7 @@ static irqreturn_t s3fwrn5_i2c_irq_thread_fn(int irq, void *phy_id)
 	}
 
 out:
-	mutex_unlock(&phy->mutex);
+	mutex_unlock(&phy->common.mutex);
 
 	return IRQ_HANDLED;
 }
@@ -197,19 +152,23 @@ static int s3fwrn5_i2c_parse_dt(struct i2c_client *client)
 	if (!np)
 		return -ENODEV;
 
-	phy->gpio_en = of_get_named_gpio(np, "en-gpios", 0);
-	if (!gpio_is_valid(phy->gpio_en)) {
+	phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_en)) {
 		/* Support also deprecated property */
-		phy->gpio_en = of_get_named_gpio(np, "s3fwrn5,en-gpios", 0);
-		if (!gpio_is_valid(phy->gpio_en))
+		phy->common.gpio_en = of_get_named_gpio(np,
+							"s3fwrn5,en-gpios",
+							0);
+		if (!gpio_is_valid(phy->common.gpio_en))
 			return -ENODEV;
 	}
 
-	phy->gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
-	if (!gpio_is_valid(phy->gpio_fw_wake)) {
+	phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_fw_wake)) {
 		/* Support also deprecated property */
-		phy->gpio_fw_wake = of_get_named_gpio(np, "s3fwrn5,fw-gpios", 0);
-		if (!gpio_is_valid(phy->gpio_fw_wake))
+		phy->common.gpio_fw_wake = of_get_named_gpio(np,
+							     "s3fwrn5,fw-gpios",
+							     0);
+		if (!gpio_is_valid(phy->common.gpio_fw_wake))
 			return -ENODEV;
 	}
 
@@ -226,8 +185,8 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (!phy)
 		return -ENOMEM;
 
-	mutex_init(&phy->mutex);
-	phy->mode = S3FWRN5_MODE_COLD;
+	mutex_init(&phy->common.mutex);
+	phy->common.mode = S3FWRN5_MODE_COLD;
 	phy->irq_skip = true;
 
 	phy->i2c_dev = client;
@@ -237,17 +196,19 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
-	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_en,
-		GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
+	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->common.gpio_en,
+				    GPIOF_OUT_INIT_HIGH, "s3fwrn5_en");
 	if (ret < 0)
 		return ret;
 
-	ret = devm_gpio_request_one(&phy->i2c_dev->dev, phy->gpio_fw_wake,
-		GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
+	ret = devm_gpio_request_one(&phy->i2c_dev->dev,
+				    phy->common.gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW, "s3fwrn5_fw_wake");
 	if (ret < 0)
 		return ret;
 
-	ret = s3fwrn5_probe(&phy->ndev, phy, &phy->i2c_dev->dev, &i2c_phy_ops);
+	ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->i2c_dev->dev,
+			    &i2c_phy_ops);
 	if (ret < 0)
 		return ret;
 
@@ -255,7 +216,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 		s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
 		S3FWRN5_I2C_DRIVER_NAME, phy);
 	if (ret)
-		s3fwrn5_remove(phy->ndev);
+		s3fwrn5_remove(phy->common.ndev);
 
 	return ret;
 }
@@ -264,7 +225,7 @@ static int s3fwrn5_i2c_remove(struct i2c_client *client)
 {
 	struct s3fwrn5_i2c_phy *phy = i2c_get_clientdata(client);
 
-	s3fwrn5_remove(phy->ndev);
+	s3fwrn5_remove(phy->common.ndev);
 
 	return 0;
 }
diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
new file mode 100644
index 0000000..5cad1f4
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Link Layer for Samsung S3FWRN5 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electrnoics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/gpio.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+
+#include "phy_common.h"
+
+void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
+{
+	struct phy_common *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+	gpio_set_value(phy->gpio_fw_wake, wake);
+	msleep(S3FWRN5_EN_WAIT_TIME);
+	mutex_unlock(&phy->mutex);
+}
+EXPORT_SYMBOL(s3fwrn5_phy_set_wake);
+
+bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
+{
+	if (phy->mode == mode)
+		return false;
+
+	phy->mode = mode;
+
+	gpio_set_value(phy->gpio_en, 1);
+	gpio_set_value(phy->gpio_fw_wake, 0);
+	if (mode == S3FWRN5_MODE_FW)
+		gpio_set_value(phy->gpio_fw_wake, 1);
+
+	if (mode != S3FWRN5_MODE_COLD) {
+		msleep(S3FWRN5_EN_WAIT_TIME);
+		gpio_set_value(phy->gpio_en, 0);
+		msleep(S3FWRN5_EN_WAIT_TIME);
+	}
+
+	return true;
+}
+EXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
+
+enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
+{
+	struct phy_common *phy = phy_id;
+	enum s3fwrn5_mode mode;
+
+	mutex_lock(&phy->mutex);
+
+	mode = phy->mode;
+
+	mutex_unlock(&phy->mutex);
+
+	return mode;
+}
+EXPORT_SYMBOL(s3fwrn5_phy_get_mode);
diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
new file mode 100644
index 0000000..b98531d
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/phy_common.h
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Link Layer for Samsung S3FWRN5 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electrnoics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#ifndef __NFC_S3FWRN5_PHY_COMMON_H
+#define __NFC_S3FWRN5_PHY_COMMON_H
+
+#include <linux/mutex.h>
+#include <net/nfc/nci_core.h>
+
+#include "s3fwrn5.h"
+
+#define S3FWRN5_EN_WAIT_TIME 20
+
+struct phy_common {
+	struct nci_dev *ndev;
+
+	int gpio_en;
+	int gpio_fw_wake;
+
+	struct mutex mutex;
+
+	enum s3fwrn5_mode mode;
+};
+
+void s3fwrn5_phy_set_wake(void *phy_id, bool wake);
+bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode);
+enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id);
+
+#endif /* __NFC_S3FWRN5_PHY_COMMON_H */
-- 
1.9.1


^ permalink raw reply related	[relevance 62%]

* [PATCH v5 net-next 4/4] nfc: s3fwrn5: Support a UART interface
  2020-12-02 11:47 85% [PATCH v5 net-next 0/4] " Bongsu Jeon
                   ` (2 preceding siblings ...)
  2020-12-02 11:47 62% ` [PATCH v5 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
@ 2020-12-02 11:47 68% ` Bongsu Jeon
  3 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 11:47 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Since S3FWRN82 NFC Chip, The UART interface can be used.
S3FWRN82 uses NCI protocol and supports I2C and UART interface.

Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/Kconfig      |  12 +++
 drivers/nfc/s3fwrn5/Makefile     |   2 +
 drivers/nfc/s3fwrn5/phy_common.c |  12 +++
 drivers/nfc/s3fwrn5/phy_common.h |   1 +
 drivers/nfc/s3fwrn5/uart.c       | 196 +++++++++++++++++++++++++++++++++++++++
 5 files changed, 223 insertions(+)
 create mode 100644 drivers/nfc/s3fwrn5/uart.c

diff --git a/drivers/nfc/s3fwrn5/Kconfig b/drivers/nfc/s3fwrn5/Kconfig
index 3f8b6da..8a6b1a7 100644
--- a/drivers/nfc/s3fwrn5/Kconfig
+++ b/drivers/nfc/s3fwrn5/Kconfig
@@ -20,3 +20,15 @@ config NFC_S3FWRN5_I2C
 	  To compile this driver as a module, choose m here. The module will
 	  be called s3fwrn5_i2c.ko.
 	  Say N if unsure.
+
+config NFC_S3FWRN82_UART
+        tristate "Samsung S3FWRN82 UART support"
+        depends on NFC_NCI && SERIAL_DEV_BUS
+        select NFC_S3FWRN5
+        help
+          This module adds support for a UART interface to the S3FWRN82 chip.
+          Select this if your platform is using the UART bus.
+
+          To compile this driver as a module, choose m here. The module will
+          be called s3fwrn82_uart.ko.
+          Say N if unsure.
diff --git a/drivers/nfc/s3fwrn5/Makefile b/drivers/nfc/s3fwrn5/Makefile
index 6b6f52d..7da827a 100644
--- a/drivers/nfc/s3fwrn5/Makefile
+++ b/drivers/nfc/s3fwrn5/Makefile
@@ -5,6 +5,8 @@
 
 s3fwrn5-objs = core.o firmware.o nci.o phy_common.o
 s3fwrn5_i2c-objs = i2c.o
+s3fwrn82_uart-objs = uart.o
 
 obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5.o
 obj-$(CONFIG_NFC_S3FWRN5_I2C) += s3fwrn5_i2c.o
+obj-$(CONFIG_NFC_S3FWRN82_UART) += s3fwrn82_uart.o
diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
index 5cad1f4..497b02b 100644
--- a/drivers/nfc/s3fwrn5/phy_common.c
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -47,6 +47,18 @@ bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode)
 }
 EXPORT_SYMBOL(s3fwrn5_phy_power_ctrl);
 
+void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode)
+{
+	struct phy_common *phy = phy_id;
+
+	mutex_lock(&phy->mutex);
+
+	s3fwrn5_phy_power_ctrl(phy, mode);
+
+	mutex_unlock(&phy->mutex);
+}
+EXPORT_SYMBOL(s3fwrn5_phy_set_mode);
+
 enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id)
 {
 	struct phy_common *phy = phy_id;
diff --git a/drivers/nfc/s3fwrn5/phy_common.h b/drivers/nfc/s3fwrn5/phy_common.h
index b98531d..99749c9 100644
--- a/drivers/nfc/s3fwrn5/phy_common.h
+++ b/drivers/nfc/s3fwrn5/phy_common.h
@@ -31,6 +31,7 @@ struct phy_common {
 
 void s3fwrn5_phy_set_wake(void *phy_id, bool wake);
 bool s3fwrn5_phy_power_ctrl(struct phy_common *phy, enum s3fwrn5_mode mode);
+void s3fwrn5_phy_set_mode(void *phy_id, enum s3fwrn5_mode mode);
 enum s3fwrn5_mode s3fwrn5_phy_get_mode(void *phy_id);
 
 #endif /* __NFC_S3FWRN5_PHY_COMMON_H */
diff --git a/drivers/nfc/s3fwrn5/uart.c b/drivers/nfc/s3fwrn5/uart.c
new file mode 100644
index 0000000..82ea35d
--- /dev/null
+++ b/drivers/nfc/s3fwrn5/uart.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * UART Link Layer for S3FWRN82 NCI based Driver
+ *
+ * Copyright (C) 2015 Samsung Electronics
+ * Robert Baldyga <r.baldyga@samsung.com>
+ * Copyright (C) 2020 Samsung Electronics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/nfc.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/serdev.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include "phy_common.h"
+
+#define S3FWRN82_NCI_HEADER 3
+#define S3FWRN82_NCI_IDX 2
+#define NCI_SKB_BUFF_LEN 258
+
+struct s3fwrn82_uart_phy {
+	struct phy_common common;
+	struct serdev_device *ser_dev;
+	struct sk_buff *recv_skb;
+};
+
+static int s3fwrn82_uart_write(void *phy_id, struct sk_buff *out)
+{
+	struct s3fwrn82_uart_phy *phy = phy_id;
+	int err;
+
+	err = serdev_device_write(phy->ser_dev,
+				  out->data, out->len,
+				  MAX_SCHEDULE_TIMEOUT);
+	if (err < 0)
+		return err;
+
+	return 0;
+}
+
+static const struct s3fwrn5_phy_ops uart_phy_ops = {
+	.set_wake = s3fwrn5_phy_set_wake,
+	.set_mode = s3fwrn5_phy_set_mode,
+	.get_mode = s3fwrn5_phy_get_mode,
+	.write = s3fwrn82_uart_write,
+};
+
+static int s3fwrn82_uart_read(struct serdev_device *serdev,
+			      const unsigned char *data,
+			      size_t count)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	size_t i;
+
+	for (i = 0; i < count; i++) {
+		skb_put_u8(phy->recv_skb, *data++);
+
+		if (phy->recv_skb->len < S3FWRN82_NCI_HEADER)
+			continue;
+
+		if ((phy->recv_skb->len - S3FWRN82_NCI_HEADER)
+				< phy->recv_skb->data[S3FWRN82_NCI_IDX])
+			continue;
+
+		s3fwrn5_recv_frame(phy->common.ndev, phy->recv_skb,
+				   phy->common.mode);
+		phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+		if (!phy->recv_skb)
+			return 0;
+	}
+
+	return i;
+}
+
+static const struct serdev_device_ops s3fwrn82_serdev_ops = {
+	.receive_buf = s3fwrn82_uart_read,
+	.write_wakeup = serdev_device_write_wakeup,
+};
+
+static const struct of_device_id s3fwrn82_uart_of_match[] = {
+	{ .compatible = "samsung,s3fwrn82", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, s3fwrn82_uart_of_match);
+
+static int s3fwrn82_uart_parse_dt(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+	struct device_node *np = serdev->dev.of_node;
+
+	if (!np)
+		return -ENODEV;
+
+	phy->common.gpio_en = of_get_named_gpio(np, "en-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_en))
+		return -ENODEV;
+
+	phy->common.gpio_fw_wake = of_get_named_gpio(np, "wake-gpios", 0);
+	if (!gpio_is_valid(phy->common.gpio_fw_wake))
+		return -ENODEV;
+
+	return 0;
+}
+
+static int s3fwrn82_uart_probe(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy;
+	int ret = -ENOMEM;
+
+	phy = devm_kzalloc(&serdev->dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		goto err_exit;
+
+	phy->recv_skb = alloc_skb(NCI_SKB_BUFF_LEN, GFP_KERNEL);
+	if (!phy->recv_skb)
+		goto err_exit;
+
+	mutex_init(&phy->common.mutex);
+	phy->common.mode = S3FWRN5_MODE_COLD;
+
+	phy->ser_dev = serdev;
+	serdev_device_set_drvdata(serdev, phy);
+	serdev_device_set_client_ops(serdev, &s3fwrn82_serdev_ops);
+	ret = serdev_device_open(serdev);
+	if (ret) {
+		dev_err(&serdev->dev, "Unable to open device\n");
+		goto err_skb;
+	}
+
+	ret = serdev_device_set_baudrate(serdev, 115200);
+	if (ret != 115200) {
+		ret = -EINVAL;
+		goto err_serdev;
+	}
+
+	serdev_device_set_flow_control(serdev, false);
+
+	ret = s3fwrn82_uart_parse_dt(serdev);
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev, phy->common.gpio_en,
+				    GPIOF_OUT_INIT_HIGH, "s3fwrn82_en");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = devm_gpio_request_one(&phy->ser_dev->dev,
+				    phy->common.gpio_fw_wake,
+				    GPIOF_OUT_INIT_LOW, "s3fwrn82_fw_wake");
+	if (ret < 0)
+		goto err_serdev;
+
+	ret = s3fwrn5_probe(&phy->common.ndev, phy, &phy->ser_dev->dev,
+			    &uart_phy_ops);
+	if (ret < 0)
+		goto err_serdev;
+
+	return ret;
+
+err_serdev:
+	serdev_device_close(serdev);
+err_skb:
+	kfree_skb(phy->recv_skb);
+err_exit:
+	return ret;
+}
+
+static void s3fwrn82_uart_remove(struct serdev_device *serdev)
+{
+	struct s3fwrn82_uart_phy *phy = serdev_device_get_drvdata(serdev);
+
+	s3fwrn5_remove(phy->common.ndev);
+	serdev_device_close(serdev);
+	kfree_skb(phy->recv_skb);
+}
+
+static struct serdev_device_driver s3fwrn82_uart_driver = {
+	.probe = s3fwrn82_uart_probe,
+	.remove = s3fwrn82_uart_remove,
+	.driver = {
+		.name = "s3fwrn82_uart",
+		.of_match_table = s3fwrn82_uart_of_match,
+	},
+};
+
+module_serdev_device_driver(s3fwrn82_uart_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("UART driver for Samsung NFC");
+MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
-- 
1.9.1


^ permalink raw reply related	[relevance 68%]

* Re: [PATCH v5 net-next 1/4] dt-bindings: net: nfc: s3fwrn5: Support a UART interface
  @ 2020-12-02 22:16 90%     ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 22:16 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

On Thu, Dec 3, 2020 at 2:16 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Wed, Dec 02, 2020 at 08:47:38PM +0900, Bongsu Jeon wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > Since S3FWRN82 NFC Chip, The UART interface can be used.
> > S3FWRN82 supports I2C and UART interface.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> > ---
> >  .../bindings/net/nfc/samsung,s3fwrn5.yaml          | 31 +++++++++++++++++++---
> >  1 file changed, 28 insertions(+), 3 deletions(-)
> >
>
> Reviewed-by: Krzysztof Kozlowski <krzk@kernel.org>
>
> Best regards,
> Krzysztof

Thanks a lot for advising and reviewing my patches.

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next v3] net/nfc/nci: Support NCI 2.x initial sequence
  @ 2020-12-02 22:18 90%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 22:18 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: linux-nfc, linux-kernel, netdev, Bongsu Jeon

On Tue, Dec 1, 2020 at 11:48 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Fri, 27 Nov 2020 22:36:31 +0900 bongsu.jeon2@gmail.com wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > implement the NCI 2.x initial sequence to support NCI 2.x NFCC.
> > Since NCI 2.0, CORE_RESET and CORE_INIT sequence have been changed.
> > If NFCEE supports NCI 2.x, then NCI 2.x initial sequence will work.
> >
> > In NCI 1.0, Initial sequence and payloads are as below:
> > (DH)                     (NFCC)
> >  |  -- CORE_RESET_CMD --> |
> >  |  <-- CORE_RESET_RSP -- |
> >  |  -- CORE_INIT_CMD -->  |
> >  |  <-- CORE_INIT_RSP --  |
> >  CORE_RESET_RSP payloads are Status, NCI version, Configuration Status.
> >  CORE_INIT_CMD payloads are empty.
> >  CORE_INIT_RSP payloads are Status, NFCC Features,
> >     Number of Supported RF Interfaces, Supported RF Interface,
> >     Max Logical Connections, Max Routing table Size,
> >     Max Control Packet Payload Size, Max Size for Large Parameters,
> >     Manufacturer ID, Manufacturer Specific Information.
> >
> > In NCI 2.0, Initial Sequence and Parameters are as below:
> > (DH)                     (NFCC)
> >  |  -- CORE_RESET_CMD --> |
> >  |  <-- CORE_RESET_RSP -- |
> >  |  <-- CORE_RESET_NTF -- |
> >  |  -- CORE_INIT_CMD -->  |
> >  |  <-- CORE_INIT_RSP --  |
> >  CORE_RESET_RSP payloads are Status.
> >  CORE_RESET_NTF payloads are Reset Trigger,
> >     Configuration Status, NCI Version, Manufacturer ID,
> >     Manufacturer Specific Information Length,
> >     Manufacturer Specific Information.
> >  CORE_INIT_CMD payloads are Feature1, Feature2.
> >  CORE_INIT_RSP payloads are Status, NFCC Features,
> >     Max Logical Connections, Max Routing Table Size,
> >     Max Control Packet Payload Size,
> >     Max Data Packet Payload Size of the Static HCI Connection,
> >     Number of Credits of the Static HCI Connection,
> >     Max NFC-V RF Frame Size, Number of Supported RF Interfaces,
> >     Supported RF Interfaces.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
>
> >  static void nci_init_req(struct nci_dev *ndev, unsigned long opt)
> >  {
> > -     nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
> > +     struct nci_core_init_v2_cmd *cmd = (struct nci_core_init_v2_cmd *)opt;
> > +
> > +     if (!cmd)
> > +             nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
> > +     else
> > +             /* if nci version is 2.0, then use the feature parameters */
> > +             nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD,
> > +                          sizeof(struct nci_core_init_v2_cmd), cmd);
>
> This would be better written as:
>
>         u8 plen = 0;
>
>         if (opt)
>                 plen = sizeof(struct nci_core_init_v2_cmd);
>
>         nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, plen, (void *)opt);
>
> > +
>
> unnecessary empty line
>
> >  }
> >
> >  static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
> > @@ -497,8 +505,18 @@ static int nci_open_device(struct nci_dev *ndev)
> >       }
> >
> >       if (!rc) {
> > -             rc = __nci_request(ndev, nci_init_req, 0,
> > -                                msecs_to_jiffies(NCI_INIT_TIMEOUT));
> > +             if (!(ndev->nci_ver & NCI_VER_2_MASK)) {
> > +                     rc = __nci_request(ndev, nci_init_req, 0,
> > +                                        msecs_to_jiffies(NCI_INIT_TIMEOUT));
> > +             } else {
> > +                     struct nci_core_init_v2_cmd nci_init_v2_cmd;
> > +
> > +                     nci_init_v2_cmd.feature1 = NCI_FEATURE_DISABLE;
> > +                     nci_init_v2_cmd.feature2 = NCI_FEATURE_DISABLE;
> > +
> > +                     rc = __nci_request(ndev, nci_init_req, (unsigned long)&nci_init_v2_cmd,
> > +                                        msecs_to_jiffies(NCI_INIT_TIMEOUT));
> > +             }
>
> again please try to pull out the common code:
>
>         struct nci_core_init_v2_cmd nci_init_v2_cmd = {
>                 .feature1 = NCI_FEATURE_DISABLE;
>                 .feature2 = NCI_FEATURE_DISABLE;
>         };
>         unsigned long opt = 0;
>
>         if (ndev->nci_ver & NCI_VER_2_MASK)
>                 opt = (unsigned long)&nci_init_v2_cmd;
>
>         rc = __nci_request(ndev, nci_init_req, opt,
>                            msecs_to_jiffies(NCI_INIT_TIMEOUT));
>
>
> >       }
>
> > -static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
> > +static unsigned char nci_core_init_rsp_packet_v1(struct nci_dev *ndev, struct sk_buff *skb)
> >  {
> >       struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
> >       struct nci_core_init_rsp_2 *rsp_2;
> > @@ -48,16 +51,14 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
> >       pr_debug("status 0x%x\n", rsp_1->status);
> >
> >       if (rsp_1->status != NCI_STATUS_OK)
> > -             goto exit;
> > +             return rsp_1->status;
> >
> >       ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
> >       ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
> >
> > -     if (ndev->num_supported_rf_interfaces >
> > -         NCI_MAX_SUPPORTED_RF_INTERFACES) {
> > -             ndev->num_supported_rf_interfaces =
> > -                     NCI_MAX_SUPPORTED_RF_INTERFACES;
> > -     }
> > +     ndev->num_supported_rf_interfaces =
> > +             min((int)ndev->num_supported_rf_interfaces,
> > +                 NCI_MAX_SUPPORTED_RF_INTERFACES);
> >
> >       memcpy(ndev->supported_rf_interfaces,
> >              rsp_1->supported_rf_interfaces,
> > @@ -77,6 +78,58 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
> >       ndev->manufact_specific_info =
> >               __le32_to_cpu(rsp_2->manufact_specific_info);
> >
> > +     return NCI_STATUS_OK;
> > +}
> > +
> > +static unsigned char nci_core_init_rsp_packet_v2(struct nci_dev *ndev, struct sk_buff *skb)
> > +{
> > +     struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
> > +     unsigned char rf_interface_idx = 0;
>
> Prefer the use of u8 type in the kernel
>
> > +     unsigned char rf_extension_cnt = 0;
> > +     unsigned char *supported_rf_interface = rsp->supported_rf_interfaces;
>
> Please order the variable declarations longest to shortest.
> Don't initialize them inline if that'd cause the order to break.
>
> > +     pr_debug("status %x\n", rsp->status);
> > +
> > +     if (rsp->status != NCI_STATUS_OK)
> > +             return rsp->status;
> > +

Thank you for your advice.
I will send a new version.

^ permalink raw reply	[relevance 90%]

* [PATCH net-next v4] net/nfc/nci: Support NCI 2.x initial sequence
@ 2020-12-02 22:31 64% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-02 22:31 UTC (permalink / raw)
  To: kuba; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

implement the NCI 2.x initial sequence to support NCI 2.x NFCC.
Since NCI 2.0, CORE_RESET and CORE_INIT sequence have been changed.
If NFCEE supports NCI 2.x, then NCI 2.x initial sequence will work.

In NCI 1.0, Initial sequence and payloads are as below:
(DH)                     (NFCC)
 |  -- CORE_RESET_CMD --> |
 |  <-- CORE_RESET_RSP -- |
 |  -- CORE_INIT_CMD -->  |
 |  <-- CORE_INIT_RSP --  |
 CORE_RESET_RSP payloads are Status, NCI version, Configuration Status.
 CORE_INIT_CMD payloads are empty.
 CORE_INIT_RSP payloads are Status, NFCC Features,
    Number of Supported RF Interfaces, Supported RF Interface,
    Max Logical Connections, Max Routing table Size,
    Max Control Packet Payload Size, Max Size for Large Parameters,
    Manufacturer ID, Manufacturer Specific Information.

In NCI 2.0, Initial Sequence and Parameters are as below:
(DH)                     (NFCC)
 |  -- CORE_RESET_CMD --> |
 |  <-- CORE_RESET_RSP -- |
 |  <-- CORE_RESET_NTF -- |
 |  -- CORE_INIT_CMD -->  |
 |  <-- CORE_INIT_RSP --  |
 CORE_RESET_RSP payloads are Status.
 CORE_RESET_NTF payloads are Reset Trigger,
    Configuration Status, NCI Version, Manufacturer ID,
    Manufacturer Specific Information Length,
    Manufacturer Specific Information.
 CORE_INIT_CMD payloads are Feature1, Feature2.
 CORE_INIT_RSP payloads are Status, NFCC Features,
    Max Logical Connections, Max Routing Table Size,
    Max Control Packet Payload Size,
    Max Data Packet Payload Size of the Static HCI Connection,
    Number of Credits of the Static HCI Connection,
    Max NFC-V RF Frame Size, Number of Supported RF Interfaces,
    Supported RF Interfaces.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---

 Changes in v4:
  - remove the unnecessary empty line.
  - pull out the common code.
  - change the unsigned char to u8.
  - order the variable declarations longest to shortest.

 Changes in v3:
  - remove the unused struct nci_core_reset_rsp_nci_ver2.
  - remove the __packed because of no need.
  - remove the unnecessary brackets.
  - change the asignment code for ndev->num_supported_rf_interfaces.

 Changes in v2:
  - fix the warning of type casting.
  - changed the __u8 type to unsigned char.

 include/net/nfc/nci.h | 34 ++++++++++++++++++
 net/nfc/nci/core.c    | 18 ++++++++--
 net/nfc/nci/ntf.c     | 21 +++++++++++
 net/nfc/nci/rsp.c     | 81 +++++++++++++++++++++++++++++++++++--------
 4 files changed, 138 insertions(+), 16 deletions(-)

diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index 0550e0380b8d..e82f55f543bb 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -25,6 +25,8 @@
 #define NCI_MAX_PARAM_LEN					251
 #define NCI_MAX_PAYLOAD_SIZE					255
 #define NCI_MAX_PACKET_SIZE					258
+#define NCI_MAX_LARGE_PARAMS_NCI_v2				15
+#define NCI_VER_2_MASK						0x20
 
 /* NCI Status Codes */
 #define NCI_STATUS_OK						0x00
@@ -131,6 +133,9 @@
 #define NCI_LF_CON_BITR_F_212					0x02
 #define NCI_LF_CON_BITR_F_424					0x04
 
+/* NCI 2.x Feature Enable Bit */
+#define NCI_FEATURE_DISABLE					0x00
+
 /* NCI Reset types */
 #define NCI_RESET_TYPE_KEEP_CONFIG				0x00
 #define NCI_RESET_TYPE_RESET_CONFIG				0x01
@@ -220,6 +225,11 @@ struct nci_core_reset_cmd {
 } __packed;
 
 #define NCI_OP_CORE_INIT_CMD		nci_opcode_pack(NCI_GID_CORE, 0x01)
+/* To support NCI 2.x */
+struct nci_core_init_v2_cmd {
+	u8	feature1;
+	u8	feature2;
+};
 
 #define NCI_OP_CORE_SET_CONFIG_CMD	nci_opcode_pack(NCI_GID_CORE, 0x02)
 struct set_config_param {
@@ -334,6 +344,20 @@ struct nci_core_init_rsp_2 {
 	__le32	manufact_specific_info;
 } __packed;
 
+/* To support NCI ver 2.x */
+struct nci_core_init_rsp_nci_ver2 {
+	u8	status;
+	__le32	nfcc_features;
+	u8	max_logical_connections;
+	__le16	max_routing_table_size;
+	u8	max_ctrl_pkt_payload_len;
+	u8	max_data_pkt_hci_payload_len;
+	u8	number_of_hci_credit;
+	__le16	max_nfc_v_frame_size;
+	u8	num_supported_rf_interfaces;
+	u8	supported_rf_interfaces[];
+} __packed;
+
 #define NCI_OP_CORE_SET_CONFIG_RSP	nci_opcode_pack(NCI_GID_CORE, 0x02)
 struct nci_core_set_config_rsp {
 	__u8	status;
@@ -372,6 +396,16 @@ struct nci_nfcee_discover_rsp {
 /* --------------------------- */
 /* ---- NCI Notifications ---- */
 /* --------------------------- */
+#define NCI_OP_CORE_RESET_NTF		nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_ntf {
+	u8	reset_trigger;
+	u8	config_status;
+	u8	nci_ver;
+	u8	manufact_id;
+	u8	manufacturer_specific_len;
+	__le32	manufact_specific_info;
+} __packed;
+
 #define NCI_OP_CORE_CONN_CREDITS_NTF	nci_opcode_pack(NCI_GID_CORE, 0x06)
 struct conn_credit_entry {
 	__u8	conn_id;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 4953ee5146e1..e64727e1a72f 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -165,7 +165,12 @@ static void nci_reset_req(struct nci_dev *ndev, unsigned long opt)
 
 static void nci_init_req(struct nci_dev *ndev, unsigned long opt)
 {
-	nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, 0, NULL);
+	u8 plen = 0;
+
+	if (opt)
+		plen = sizeof(struct nci_core_init_v2_cmd);
+
+	nci_send_cmd(ndev, NCI_OP_CORE_INIT_CMD, plen, (void *)opt);
 }
 
 static void nci_init_complete_req(struct nci_dev *ndev, unsigned long opt)
@@ -497,7 +502,16 @@ static int nci_open_device(struct nci_dev *ndev)
 	}
 
 	if (!rc) {
-		rc = __nci_request(ndev, nci_init_req, 0,
+		struct nci_core_init_v2_cmd nci_init_v2_cmd = {
+			.feature1 = NCI_FEATURE_DISABLE,
+			.feature2 = NCI_FEATURE_DISABLE
+		};
+		unsigned long opt = 0;
+
+		if (!(ndev->nci_ver & NCI_VER_2_MASK))
+			opt = (unsigned long)&nci_init_v2_cmd;
+
+		rc = __nci_request(ndev, nci_init_req, opt,
 				   msecs_to_jiffies(NCI_INIT_TIMEOUT));
 	}
 
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 33e1170817f0..98af04c86b2c 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -27,6 +27,23 @@
 
 /* Handle NCI Notification packets */
 
+static void nci_core_reset_ntf_packet(struct nci_dev *ndev,
+				      struct sk_buff *skb)
+{
+	/* Handle NCI 2.x core reset notification */
+	struct nci_core_reset_ntf *ntf = (void *)skb->data;
+
+	ndev->nci_ver = ntf->nci_ver;
+	pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+		 ntf->nci_ver, ntf->config_status);
+
+	ndev->manufact_id = ntf->manufact_id;
+	ndev->manufact_specific_info =
+		__le32_to_cpu(ntf->manufact_specific_info);
+
+	nci_req_complete(ndev, NCI_STATUS_OK);
+}
+
 static void nci_core_conn_credits_ntf_packet(struct nci_dev *ndev,
 					     struct sk_buff *skb)
 {
@@ -756,6 +773,10 @@ void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	}
 
 	switch (ntf_opcode) {
+	case NCI_OP_CORE_RESET_NTF:
+		nci_core_reset_ntf_packet(ndev, skb);
+		break;
+
 	case NCI_OP_CORE_CONN_CREDITS_NTF:
 		nci_core_conn_credits_ntf_packet(ndev, skb);
 		break;
diff --git a/net/nfc/nci/rsp.c b/net/nfc/nci/rsp.c
index a48297b79f34..e9605922a322 100644
--- a/net/nfc/nci/rsp.c
+++ b/net/nfc/nci/rsp.c
@@ -31,16 +31,19 @@ static void nci_core_reset_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 
 	pr_debug("status 0x%x\n", rsp->status);
 
-	if (rsp->status == NCI_STATUS_OK) {
-		ndev->nci_ver = rsp->nci_ver;
-		pr_debug("nci_ver 0x%x, config_status 0x%x\n",
-			 rsp->nci_ver, rsp->config_status);
-	}
+	/* Handle NCI 1.x ver */
+	if (skb->len != 1) {
+		if (rsp->status == NCI_STATUS_OK) {
+			ndev->nci_ver = rsp->nci_ver;
+			pr_debug("nci_ver 0x%x, config_status 0x%x\n",
+				 rsp->nci_ver, rsp->config_status);
+		}
 
-	nci_req_complete(ndev, rsp->status);
+		nci_req_complete(ndev, rsp->status);
+	}
 }
 
-static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+static u8 nci_core_init_rsp_packet_v1(struct nci_dev *ndev, struct sk_buff *skb)
 {
 	struct nci_core_init_rsp_1 *rsp_1 = (void *) skb->data;
 	struct nci_core_init_rsp_2 *rsp_2;
@@ -48,16 +51,14 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	pr_debug("status 0x%x\n", rsp_1->status);
 
 	if (rsp_1->status != NCI_STATUS_OK)
-		goto exit;
+		return rsp_1->status;
 
 	ndev->nfcc_features = __le32_to_cpu(rsp_1->nfcc_features);
 	ndev->num_supported_rf_interfaces = rsp_1->num_supported_rf_interfaces;
 
-	if (ndev->num_supported_rf_interfaces >
-	    NCI_MAX_SUPPORTED_RF_INTERFACES) {
-		ndev->num_supported_rf_interfaces =
-			NCI_MAX_SUPPORTED_RF_INTERFACES;
-	}
+	ndev->num_supported_rf_interfaces =
+		min((int)ndev->num_supported_rf_interfaces,
+		    NCI_MAX_SUPPORTED_RF_INTERFACES);
 
 	memcpy(ndev->supported_rf_interfaces,
 	       rsp_1->supported_rf_interfaces,
@@ -77,6 +78,58 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 	ndev->manufact_specific_info =
 		__le32_to_cpu(rsp_2->manufact_specific_info);
 
+	return NCI_STATUS_OK;
+}
+
+static u8 nci_core_init_rsp_packet_v2(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	struct nci_core_init_rsp_nci_ver2 *rsp = (void *)skb->data;
+	u8 *supported_rf_interface = rsp->supported_rf_interfaces;
+	u8 rf_interface_idx = 0;
+	u8 rf_extension_cnt = 0;
+
+	pr_debug("status %x\n", rsp->status);
+
+	if (rsp->status != NCI_STATUS_OK)
+		return rsp->status;
+
+	ndev->nfcc_features = __le32_to_cpu(rsp->nfcc_features);
+	ndev->num_supported_rf_interfaces = rsp->num_supported_rf_interfaces;
+
+	ndev->num_supported_rf_interfaces =
+		min((int)ndev->num_supported_rf_interfaces,
+		    NCI_MAX_SUPPORTED_RF_INTERFACES);
+
+	while (rf_interface_idx < ndev->num_supported_rf_interfaces) {
+		ndev->supported_rf_interfaces[rf_interface_idx++] = *supported_rf_interface++;
+
+		/* skip rf extension parameters */
+		rf_extension_cnt = *supported_rf_interface++;
+		supported_rf_interface += rf_extension_cnt;
+	}
+
+	ndev->max_logical_connections = rsp->max_logical_connections;
+	ndev->max_routing_table_size =
+			__le16_to_cpu(rsp->max_routing_table_size);
+	ndev->max_ctrl_pkt_payload_len =
+			rsp->max_ctrl_pkt_payload_len;
+	ndev->max_size_for_large_params = NCI_MAX_LARGE_PARAMS_NCI_v2;
+
+	return NCI_STATUS_OK;
+}
+
+static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	u8 status = 0;
+
+	if (!(ndev->nci_ver & NCI_VER_2_MASK))
+		status = nci_core_init_rsp_packet_v1(ndev, skb);
+	else
+		status = nci_core_init_rsp_packet_v2(ndev, skb);
+
+	if (status != NCI_STATUS_OK)
+		goto exit;
+
 	pr_debug("nfcc_features 0x%x\n",
 		 ndev->nfcc_features);
 	pr_debug("num_supported_rf_interfaces %d\n",
@@ -103,7 +156,7 @@ static void nci_core_init_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb)
 		 ndev->manufact_specific_info);
 
 exit:
-	nci_req_complete(ndev, rsp_1->status);
+	nci_req_complete(ndev, status);
 }
 
 static void nci_core_set_config_rsp_packet(struct nci_dev *ndev,
-- 
2.17.1


^ permalink raw reply related	[relevance 64%]

* [PATCH net-next] nfc: s3fwrn5: skip the NFC bootloader mode
@ 2020-12-03 15:39 82% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-03 15:39 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

If there isn't proper NFC firmware image,
Bootloader mode will be skipped.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/core.c     | 44 ++++++++++++++++++++++++----------
 drivers/nfc/s3fwrn5/firmware.c | 11 +--------
 drivers/nfc/s3fwrn5/firmware.h |  1 +
 3 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c
index f8e5d78d9078..df89bc5d7338 100644
--- a/drivers/nfc/s3fwrn5/core.c
+++ b/drivers/nfc/s3fwrn5/core.c
@@ -20,13 +20,26 @@
 				NFC_PROTO_ISO14443_B_MASK | \
 				NFC_PROTO_ISO15693_MASK)
 
+static int s3fwrn5_firmware_init(struct s3fwrn5_info *info)
+{
+	struct s3fwrn5_fw_info *fw_info = &info->fw_info;
+	int ret;
+
+	s3fwrn5_fw_init(fw_info, "sec_s3fwrn5_firmware.bin");
+
+	/* Get firmware data */
+	ret = s3fwrn5_fw_request_firmware(fw_info);
+	if (ret < 0)
+		dev_err(&fw_info->ndev->nfc_dev->dev,
+			"Failed to get fw file, ret=%02x\n", ret);
+	return ret;
+}
+
 static int s3fwrn5_firmware_update(struct s3fwrn5_info *info)
 {
 	bool need_update;
 	int ret;
 
-	s3fwrn5_fw_init(&info->fw_info, "sec_s3fwrn5_firmware.bin");
-
 	/* Update firmware */
 
 	s3fwrn5_set_wake(info, false);
@@ -109,21 +122,26 @@ static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
 	struct s3fwrn5_info *info = nci_get_drvdata(ndev);
 	int ret;
 
-	ret = s3fwrn5_firmware_update(info);
-	if (ret < 0)
-		goto out;
+	if (s3fwrn5_firmware_init(info) == 0) {
+		ret = s3fwrn5_firmware_update(info);
+		if (ret < 0)
+			goto out;
 
-	/* NCI core reset */
-
-	s3fwrn5_set_mode(info, S3FWRN5_MODE_NCI);
-	s3fwrn5_set_wake(info, true);
+		/* NCI core reset */
 
-	ret = nci_core_reset(info->ndev);
-	if (ret < 0)
-		goto out;
+		s3fwrn5_set_mode(info, S3FWRN5_MODE_NCI);
+		s3fwrn5_set_wake(info, true);
 
-	ret = nci_core_init(info->ndev);
+		ret = nci_core_reset(info->ndev);
+		if (ret < 0)
+			goto out;
 
+		ret = nci_core_init(info->ndev);
+	} else {
+		dev_info(&info->ndev->nfc_dev->dev,
+			 "skip bootloader mode\n");
+		ret = 0;
+	}
 out:
 	return ret;
 }
diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
index 4cde6dd5c019..4b5352e2b915 100644
--- a/drivers/nfc/s3fwrn5/firmware.c
+++ b/drivers/nfc/s3fwrn5/firmware.c
@@ -280,7 +280,7 @@ static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info)
 
 #define S3FWRN5_FW_IMAGE_HEADER_SIZE 44
 
-static int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info)
+int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info)
 {
 	struct s3fwrn5_fw_image *fw = &fw_info->fw;
 	u32 sig_off;
@@ -358,15 +358,6 @@ int s3fwrn5_fw_setup(struct s3fwrn5_fw_info *fw_info)
 	struct s3fwrn5_fw_cmd_get_bootinfo_rsp bootinfo;
 	int ret;
 
-	/* Get firmware data */
-
-	ret = s3fwrn5_fw_request_firmware(fw_info);
-	if (ret < 0) {
-		dev_err(&fw_info->ndev->nfc_dev->dev,
-			"Failed to get fw file, ret=%02x\n", ret);
-		return ret;
-	}
-
 	/* Get bootloader info */
 
 	ret = s3fwrn5_fw_get_bootinfo(fw_info, &bootinfo);
diff --git a/drivers/nfc/s3fwrn5/firmware.h b/drivers/nfc/s3fwrn5/firmware.h
index 3c83e6730d30..3a82ce5837fb 100644
--- a/drivers/nfc/s3fwrn5/firmware.h
+++ b/drivers/nfc/s3fwrn5/firmware.h
@@ -89,6 +89,7 @@ struct s3fwrn5_fw_info {
 	char parity;
 };
 
+int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info);
 void s3fwrn5_fw_init(struct s3fwrn5_fw_info *fw_info, const char *fw_name);
 int s3fwrn5_fw_setup(struct s3fwrn5_fw_info *fw_info);
 bool s3fwrn5_fw_check_version(const struct s3fwrn5_fw_info *fw_info, u32 version);
-- 
2.17.1


^ permalink raw reply related	[relevance 82%]

* [PATCH v2 net-next] nfc: s3fwrn5: skip the NFC bootloader mode
@ 2020-12-03 22:52 84% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-03 22:52 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

If there isn't a proper NFC firmware image, Bootloader mode will be
skipped.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---

 ChangeLog:
  v2:
   - change the commit message.
   - change the skip handling code.

 drivers/nfc/s3fwrn5/core.c     | 23 +++++++++++++++++++++--
 drivers/nfc/s3fwrn5/firmware.c | 11 +----------
 drivers/nfc/s3fwrn5/firmware.h |  1 +
 3 files changed, 23 insertions(+), 12 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c
index f8e5d78d9078..c00b7a07c3ee 100644
--- a/drivers/nfc/s3fwrn5/core.c
+++ b/drivers/nfc/s3fwrn5/core.c
@@ -20,13 +20,26 @@
 				NFC_PROTO_ISO14443_B_MASK | \
 				NFC_PROTO_ISO15693_MASK)
 
+static int s3fwrn5_firmware_init(struct s3fwrn5_info *info)
+{
+	struct s3fwrn5_fw_info *fw_info = &info->fw_info;
+	int ret;
+
+	s3fwrn5_fw_init(fw_info, "sec_s3fwrn5_firmware.bin");
+
+	/* Get firmware data */
+	ret = s3fwrn5_fw_request_firmware(fw_info);
+	if (ret < 0)
+		dev_err(&fw_info->ndev->nfc_dev->dev,
+			"Failed to get fw file, ret=%02x\n", ret);
+	return ret;
+}
+
 static int s3fwrn5_firmware_update(struct s3fwrn5_info *info)
 {
 	bool need_update;
 	int ret;
 
-	s3fwrn5_fw_init(&info->fw_info, "sec_s3fwrn5_firmware.bin");
-
 	/* Update firmware */
 
 	s3fwrn5_set_wake(info, false);
@@ -109,6 +122,12 @@ static int s3fwrn5_nci_post_setup(struct nci_dev *ndev)
 	struct s3fwrn5_info *info = nci_get_drvdata(ndev);
 	int ret;
 
+	if (s3fwrn5_firmware_init(info)) {
+		//skip bootloader mode
+		ret = 0;
+		goto out;
+	}
+
 	ret = s3fwrn5_firmware_update(info);
 	if (ret < 0)
 		goto out;
diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
index 4cde6dd5c019..4b5352e2b915 100644
--- a/drivers/nfc/s3fwrn5/firmware.c
+++ b/drivers/nfc/s3fwrn5/firmware.c
@@ -280,7 +280,7 @@ static int s3fwrn5_fw_complete_update_mode(struct s3fwrn5_fw_info *fw_info)
 
 #define S3FWRN5_FW_IMAGE_HEADER_SIZE 44
 
-static int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info)
+int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info)
 {
 	struct s3fwrn5_fw_image *fw = &fw_info->fw;
 	u32 sig_off;
@@ -358,15 +358,6 @@ int s3fwrn5_fw_setup(struct s3fwrn5_fw_info *fw_info)
 	struct s3fwrn5_fw_cmd_get_bootinfo_rsp bootinfo;
 	int ret;
 
-	/* Get firmware data */
-
-	ret = s3fwrn5_fw_request_firmware(fw_info);
-	if (ret < 0) {
-		dev_err(&fw_info->ndev->nfc_dev->dev,
-			"Failed to get fw file, ret=%02x\n", ret);
-		return ret;
-	}
-
 	/* Get bootloader info */
 
 	ret = s3fwrn5_fw_get_bootinfo(fw_info, &bootinfo);
diff --git a/drivers/nfc/s3fwrn5/firmware.h b/drivers/nfc/s3fwrn5/firmware.h
index 3c83e6730d30..3a82ce5837fb 100644
--- a/drivers/nfc/s3fwrn5/firmware.h
+++ b/drivers/nfc/s3fwrn5/firmware.h
@@ -89,6 +89,7 @@ struct s3fwrn5_fw_info {
 	char parity;
 };
 
+int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info);
 void s3fwrn5_fw_init(struct s3fwrn5_fw_info *fw_info, const char *fw_name);
 int s3fwrn5_fw_setup(struct s3fwrn5_fw_info *fw_info);
 bool s3fwrn5_fw_check_version(const struct s3fwrn5_fw_info *fw_info, u32 version);
-- 
2.17.1


^ permalink raw reply related	[relevance 84%]

* [PATCH net-next] nfc: s3fwrn5: Change irqflags
@ 2020-12-07 11:38 90% Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-07 11:38 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

change irqflags from IRQF_TRIGGER_HIGH to IRQF_TRIGGER_RISING for stable
Samsung's nfc interrupt handling.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/i2c.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index e1bdde105f24..016f6b6df849 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -213,7 +213,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 		return ret;
 
 	ret = devm_request_threaded_irq(&client->dev, phy->i2c_dev->irq, NULL,
-		s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+		s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
 		S3FWRN5_I2C_DRIVER_NAME, phy);
 	if (ret)
 		s3fwrn5_remove(phy->common.ndev);
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* Re: [PATCH net-next] nfc: s3fwrn5: Change irqflags
  @ 2020-12-07 13:39 89%   ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-07 13:39 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

On Mon, Dec 7, 2020 at 8:51 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Mon, Dec 07, 2020 at 08:38:27PM +0900, Bongsu Jeon wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > change irqflags from IRQF_TRIGGER_HIGH to IRQF_TRIGGER_RISING for stable
> > Samsung's nfc interrupt handling.
>
> 1. Describe in commit title/subject the change. Just a word "change irqflags" is
>    not enough.
>
Ok. I'll update it.

> 2. Describe in commit message what you are trying to fix. Before was not
>    stable? The "for stable interrupt handling" is a little bit vauge.
>
Usually, Samsung's NFC Firmware sends an i2c frame as below.

1. NFC Firmware sets the gpio(interrupt pin) high when there is an i2c
frame to send.
2. If the CPU's I2C master has received the i2c frame, NFC F/W sets
the gpio low.

NFC driver's i2c interrupt handler would be called in the abnormal case
as the NFC F/W task of number 2 is delayed because of other high
priority tasks.
In that case, NFC driver will try to receive the i2c frame but there
isn't any i2c frame
to send in NFC. It would cause an I2C communication problem.
This case would hardly happen.
But, I changed the interrupt as a defense code.
If Driver uses the TRIGGER_RISING not LEVEL trigger, there would be no problem
even if the NFC F/W task is delayed.

> 3. This is contradictory to the bindings and current DTS. I think the
>    driver should not force the specific trigger type because I could
>    imagine some configuration that the actual interrupt to the CPU is
>    routed differently.
>
>    Instead, how about removing the trigger flags here and fixing the DTS
>    and bindings example?
>

As I mentioned before,
I changed this code because of Samsung NFC's I2C Communication way.
So, I think that it is okay for the nfc driver to force the specific
trigger type( EDGE_RISING).

What do you think about it?

> Best regards,
> Krzysztof
>
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> > ---
> >  drivers/nfc/s3fwrn5/i2c.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
> > index e1bdde105f24..016f6b6df849 100644
> > --- a/drivers/nfc/s3fwrn5/i2c.c
> > +++ b/drivers/nfc/s3fwrn5/i2c.c
> > @@ -213,7 +213,7 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
> >               return ret;
> >
> >       ret = devm_request_threaded_irq(&client->dev, phy->i2c_dev->irq, NULL,
> > -             s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
> > +             s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
> >               S3FWRN5_I2C_DRIVER_NAME, phy);
> >       if (ret)
> >               s3fwrn5_remove(phy->common.ndev);
> > --
> > 2.17.1
> >

^ permalink raw reply	[relevance 89%]

* Re: [PATCH net-next] nfc: s3fwrn5: Change irqflags
  @ 2020-12-07 14:26 90%       ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-07 14:26 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

On Mon, Dec 7, 2020 at 11:13 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Mon, Dec 07, 2020 at 10:39:01PM +0900, Bongsu Jeon wrote:
> > On Mon, Dec 7, 2020 at 8:51 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
> > >
> > > On Mon, Dec 07, 2020 at 08:38:27PM +0900, Bongsu Jeon wrote:
> > > > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> > > >
> > > > change irqflags from IRQF_TRIGGER_HIGH to IRQF_TRIGGER_RISING for stable
> > > > Samsung's nfc interrupt handling.
> > >
> > > 1. Describe in commit title/subject the change. Just a word "change irqflags" is
> > >    not enough.
> > >
> > Ok. I'll update it.
> >
> > > 2. Describe in commit message what you are trying to fix. Before was not
> > >    stable? The "for stable interrupt handling" is a little bit vauge.
> > >
> > Usually, Samsung's NFC Firmware sends an i2c frame as below.
> >
> > 1. NFC Firmware sets the gpio(interrupt pin) high when there is an i2c
> > frame to send.
> > 2. If the CPU's I2C master has received the i2c frame, NFC F/W sets
> > the gpio low.
> >
> > NFC driver's i2c interrupt handler would be called in the abnormal case
> > as the NFC F/W task of number 2 is delayed because of other high
> > priority tasks.
> > In that case, NFC driver will try to receive the i2c frame but there
> > isn't any i2c frame
> > to send in NFC. It would cause an I2C communication problem.
> > This case would hardly happen.
> > But, I changed the interrupt as a defense code.
> > If Driver uses the TRIGGER_RISING not LEVEL trigger, there would be no problem
> > even if the NFC F/W task is delayed.
>
> All this should be explained in commit message, not in the email.
>
Okay.  I will

> >
> > > 3. This is contradictory to the bindings and current DTS. I think the
> > >    driver should not force the specific trigger type because I could
> > >    imagine some configuration that the actual interrupt to the CPU is
> > >    routed differently.
> > >
> > >    Instead, how about removing the trigger flags here and fixing the DTS
> > >    and bindings example?
> > >
> >
> > As I mentioned before,
> > I changed this code because of Samsung NFC's I2C Communication way.
> > So, I think that it is okay for the nfc driver to force the specific
> > trigger type( EDGE_RISING).
> >
> > What do you think about it?
>
> Some different chip or some different hardware implementation could have
> the signal inverted, e.g. edge falling, not rising. This is rather
> a theoretical scenario but still such change makes the code more
> generic, configurable with DTS. Therefore trigger mode should be
> configured via DTS, not enforced by the driver.
>
Okay. I understand it.

> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 90%]

* [PATCH v2 net-next 0/2] nfc: s3fwrn5: Change I2C interrupt trigger to EDGE_RISING
@ 2020-12-08 14:10 90% Bongsu Jeon
  2020-12-08 14:10 87% ` [PATCH v2 net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Change I2C interrupt trigger type Bongsu Jeon
  2020-12-08 14:10 90% ` [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove hard coded interrupt trigger type from the i2c module Bongsu Jeon
  0 siblings, 2 replies; 79+ results
From: Bongsu Jeon @ 2020-12-08 14:10 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

For stable Samsung's I2C interrupt handling, I changed the interrupt 
trigger from IRQ_TYPE_LEVEL_HIGH to IRQ_TYPE_EDGE_RISING and removed 
the hard coded interrupt trigger type in the i2c module for the flexible 
control.

1/2 is the changed dt binding for the edge rising trigger.
2/2 is to remove the hard coded interrupt trigger type in the i2c module.

ChangeLog:
 v2:
  2/2
   - remove the hard coded interrupt trigger type.

Bongsu Jeon (2):
  dt-bindings: net: nfc: s3fwrn5: Change I2C interrupt trigger to
    EDGE_RISING
  nfc: s3fwrn5: Remove hard coded interrupt trigger type from the i2c
    module

 .../devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml      | 2 +-
 drivers/nfc/s3fwrn5/i2c.c                                 | 8 +++++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

-- 
2.17.1


^ permalink raw reply	[relevance 90%]

* [PATCH v2 net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Change I2C interrupt trigger type
  2020-12-08 14:10 90% [PATCH v2 net-next 0/2] nfc: s3fwrn5: Change I2C interrupt trigger to EDGE_RISING Bongsu Jeon
@ 2020-12-08 14:10 87% ` Bongsu Jeon
  2020-12-08 14:10 90% ` [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove hard coded interrupt trigger type from the i2c module Bongsu Jeon
  1 sibling, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-08 14:10 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Change interrupt trigger from IRQ_TYPE_LEVEL_HIGH to IRQ_TYPE_EDGE_RISING
 for stable NFC I2C interrupt handling.
Samsung's NFC Firmware sends an i2c frame as below.
1. NFC Firmware sets the GPIO(interrupt pin) high when there is an i2c
 frame to send.
2. If the CPU's I2C master has received the i2c frame, NFC F/W sets the
GPIO low.
NFC driver's i2c interrupt handler would be called in the abnormal case
as the NFC FW task of number 2 is delayed because of other high priority
tasks.
In that case, NFC driver will try to receive the i2c frame but there isn't
 any i2c frame to send in NFC.
It would cause an I2C communication problem. This case would hardly happen.
But, I changed the interrupt as a defense code.
If Driver uses the TRIGGER_RISING instead of the LEVEL trigger,
there would be no problem even if the NFC FW task is delayed.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
index ca3904bf90e0..477066e2b821 100644
--- a/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
+++ b/Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
@@ -76,7 +76,7 @@ examples:
             reg = <0x27>;
 
             interrupt-parent = <&gpa1>;
-            interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+            interrupts = <3 IRQ_TYPE_EDGE_RISING>;
 
             en-gpios = <&gpf1 4 GPIO_ACTIVE_HIGH>;
             wake-gpios = <&gpj0 2 GPIO_ACTIVE_HIGH>;
-- 
2.17.1


^ permalink raw reply related	[relevance 87%]

* [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove hard coded interrupt trigger type from the i2c module
  2020-12-08 14:10 90% [PATCH v2 net-next 0/2] nfc: s3fwrn5: Change I2C interrupt trigger to EDGE_RISING Bongsu Jeon
  2020-12-08 14:10 87% ` [PATCH v2 net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Change I2C interrupt trigger type Bongsu Jeon
@ 2020-12-08 14:10 90% ` Bongsu Jeon
  1 sibling, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-08 14:10 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, devicetree, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

For the flexible control of interrupt trigger type, remove the hard coded
interrupt trigger type in the i2c module. The trigger type will be loaded
 from a dts.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/i2c.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c
index e1bdde105f24..42f1f610ac2c 100644
--- a/drivers/nfc/s3fwrn5/i2c.c
+++ b/drivers/nfc/s3fwrn5/i2c.c
@@ -179,6 +179,8 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 				  const struct i2c_device_id *id)
 {
 	struct s3fwrn5_i2c_phy *phy;
+	struct irq_data *irq_data;
+	unsigned long irqflags;
 	int ret;
 
 	phy = devm_kzalloc(&client->dev, sizeof(*phy), GFP_KERNEL);
@@ -212,8 +214,11 @@ static int s3fwrn5_i2c_probe(struct i2c_client *client,
 	if (ret < 0)
 		return ret;
 
+	irq_data = irq_get_irq_data(client->irq);
+	irqflags = irqd_get_trigger_type(irq_data) | IRQF_ONESHOT;
+
 	ret = devm_request_threaded_irq(&client->dev, phy->i2c_dev->irq, NULL,
-		s3fwrn5_i2c_irq_thread_fn, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+		s3fwrn5_i2c_irq_thread_fn, irqflags,
 		S3FWRN5_I2C_DRIVER_NAME, phy);
 	if (ret)
 		s3fwrn5_remove(phy->common.ndev);
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* [PATCH net-next] nfc: s3fwrn5: Release the nfc firmware
@ 2020-12-13  9:58 90% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-13  9:58 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

add the code to release the nfc firmware when the firmware image size is
wrong.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/firmware.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/firmware.c b/drivers/nfc/s3fwrn5/firmware.c
index 4b5352e2b915..b70737b3070e 100644
--- a/drivers/nfc/s3fwrn5/firmware.c
+++ b/drivers/nfc/s3fwrn5/firmware.c
@@ -293,8 +293,10 @@ int s3fwrn5_fw_request_firmware(struct s3fwrn5_fw_info *fw_info)
 	if (ret < 0)
 		return ret;
 
-	if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE)
+	if (fw->fw->size < S3FWRN5_FW_IMAGE_HEADER_SIZE) {
+		release_firmware(fw->fw);
 		return -EINVAL;
+	}
 
 	memcpy(fw->date, fw->fw->data + 0x00, 12);
 	fw->date[12] = '\0';
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* [PATCH net-next] nfc: s3fwrn5: Remove the delay for nfc sleep
@ 2020-12-13 10:12 90% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-13 10:12 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

remove the delay for nfc sleep because nfc doesn't need the sleep delay.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/phy_common.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
index 497b02b30ae7..81318478d5fd 100644
--- a/drivers/nfc/s3fwrn5/phy_common.c
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -20,7 +20,8 @@ void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
 
 	mutex_lock(&phy->mutex);
 	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME);
+	if (wake)
+		msleep(S3FWRN5_EN_WAIT_TIME);
 	mutex_unlock(&phy->mutex);
 }
 EXPORT_SYMBOL(s3fwrn5_phy_set_wake);
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* [PATCH net-next] nfc: s3fwrn5: Remove unused nci prop commands
@ 2020-12-14 11:46 88% Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-14 11:46 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

remove the unused nci prop commands that samsung driver doesn't use.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/nci.c | 25 -------------------------
 drivers/nfc/s3fwrn5/nci.h | 22 ----------------------
 2 files changed, 47 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/nci.c b/drivers/nfc/s3fwrn5/nci.c
index 103bf5c92bdc..f042d3eaf8f6 100644
--- a/drivers/nfc/s3fwrn5/nci.c
+++ b/drivers/nfc/s3fwrn5/nci.c
@@ -21,31 +21,11 @@ static int s3fwrn5_nci_prop_rsp(struct nci_dev *ndev, struct sk_buff *skb)
 }
 
 static struct nci_driver_ops s3fwrn5_nci_prop_ops[] = {
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_AGAIN),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_GET_RFREG),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
 	{
 		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
 				NCI_PROP_SET_RFREG),
 		.rsp = s3fwrn5_nci_prop_rsp,
 	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_GET_RFREG_VER),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_SET_RFREG_VER),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
 	{
 		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
 				NCI_PROP_START_RFREG),
@@ -61,11 +41,6 @@ static struct nci_driver_ops s3fwrn5_nci_prop_ops[] = {
 				NCI_PROP_FW_CFG),
 		.rsp = s3fwrn5_nci_prop_rsp,
 	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_WR_RESET),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
 };
 
 void s3fwrn5_nci_get_prop_ops(struct nci_driver_ops **ops, size_t *n)
diff --git a/drivers/nfc/s3fwrn5/nci.h b/drivers/nfc/s3fwrn5/nci.h
index 23c0b28f247a..a80f0fb082a8 100644
--- a/drivers/nfc/s3fwrn5/nci.h
+++ b/drivers/nfc/s3fwrn5/nci.h
@@ -11,9 +11,6 @@
 
 #include "s3fwrn5.h"
 
-#define NCI_PROP_AGAIN		0x01
-
-#define NCI_PROP_GET_RFREG	0x21
 #define NCI_PROP_SET_RFREG	0x22
 
 struct nci_prop_set_rfreg_cmd {
@@ -25,23 +22,6 @@ struct nci_prop_set_rfreg_rsp {
 	__u8 status;
 };
 
-#define NCI_PROP_GET_RFREG_VER	0x24
-
-struct nci_prop_get_rfreg_ver_rsp {
-	__u8 status;
-	__u8 data[8];
-};
-
-#define NCI_PROP_SET_RFREG_VER	0x25
-
-struct nci_prop_set_rfreg_ver_cmd {
-	__u8 data[8];
-};
-
-struct nci_prop_set_rfreg_ver_rsp {
-	__u8 status;
-};
-
 #define NCI_PROP_START_RFREG	0x26
 
 struct nci_prop_start_rfreg_rsp {
@@ -70,8 +50,6 @@ struct nci_prop_fw_cfg_rsp {
 	__u8 status;
 };
 
-#define NCI_PROP_WR_RESET	0x2f
-
 void s3fwrn5_nci_get_prop_ops(struct nci_driver_ops **ops, size_t *n);
 int s3fwrn5_nci_rf_configure(struct s3fwrn5_info *info, const char *fw_name);
 
-- 
2.17.1


^ permalink raw reply related	[relevance 88%]

* [PATCH net-next] MAINTAINERS: Update maintainer for SAMSUNG S3FWRN5 NFC
@ 2020-12-14 12:28 90% Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-14 12:28 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

add an email to look after the SAMSUNG NFC driver.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 5c1a6ba5ef26..cb1634eb010d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15425,6 +15425,7 @@ F:	include/media/drv-intf/s3c_camif.h
 SAMSUNG S3FWRN5 NFC DRIVER
 M:	Krzysztof Kozlowski <krzk@kernel.org>
 M:	Krzysztof Opasiak <k.opasiak@samsung.com>
+M:	Bongsu Jeon <bongsu.jeon@samsung.com>
 L:	linux-nfc@lists.01.org (moderated for non-subscribers)
 S:	Maintained
 F:	Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* Re: [linux-nfc] [PATCH net-next] MAINTAINERS: Update maintainer for SAMSUNG S3FWRN5 NFC
  @ 2020-12-15  3:01 90%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-15  3:01 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

On Tue, Dec 15, 2020 at 12:44 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Mon, Dec 14, 2020 at 09:28:23PM +0900, Bongsu Jeon wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > add an email to look after the SAMSUNG NFC driver.
>
> Hi Bongsu,
>
> Review and testing is always appreciated. However before adding an entry
> to Maintainers, I would prefer to see some activity in maintainer-like
> tasks. So far there are none:
> https://lore.kernel.org/lkml/?q=f%3A%22Bongsu+Jeon%22
>
> Contributing patches is not the same as maintenance. Please subscribe to
> relevant mailing lists and devote effort for improving other people
> code.
>
> We had too many maintainers from many companies which did not perform
> actual maintainership for long time and clearly that's not the point.
>
> Best regards,
> Krzysztof

Ok, I  understand it.

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next] nfc: s3fwrn5: Remove unused nci prop commands
  @ 2020-12-15  3:03 90%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-15  3:03 UTC (permalink / raw)
  To: Krzysztof Kozlowski; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

On Tue, Dec 15, 2020 at 1:02 AM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>
> On Mon, Dec 14, 2020 at 08:46:58PM +0900, Bongsu Jeon wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > remove the unused nci prop commands that samsung driver doesn't use.
>
> Don't send patches one-by-one, but group them in a patchset.
>
> Previous comments apply here as well - NCI is acronym, start with
> capital letter.
>
> Best regards,
> Krzysztof
>
I will update the comments and send the patches in a series.

^ permalink raw reply	[relevance 90%]

* [PATCH v2 net-next 0/2] nfc: s3fwrn5: Refactor the s3fwrn5 module
@ 2020-12-15  6:53 90% Bongsu Jeon
  2020-12-15  6:54 90% ` [PATCH v2 net-next 1/2] nfc: s3fwrn5: Remove the delay for NFC sleep Bongsu Jeon
  2020-12-15  6:54 88% ` [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove unused NCI prop commands Bongsu Jeon
  0 siblings, 2 replies; 79+ results
From: Bongsu Jeon @ 2020-12-15  6:53 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Refactor the s3fwrn5 module.

1/2 is to remove the unneeded delay for NFC sleep.
2/2 is to remove the unused NCI prop commands.

ChangeLog:
 v2:
  - Update the commit messages.

Bongsu Jeon (2):
  nfc: s3fwrn5: Remove the delay for NFC sleep
  nfc: s3fwrn5: Remove unused NCI prop commands

 drivers/nfc/s3fwrn5/nci.c        | 25 -------------------------
 drivers/nfc/s3fwrn5/nci.h        | 22 ----------------------
 drivers/nfc/s3fwrn5/phy_common.c |  3 ++-
 3 files changed, 2 insertions(+), 48 deletions(-)

-- 
2.17.1


^ permalink raw reply	[relevance 90%]

* [PATCH v2 net-next 1/2] nfc: s3fwrn5: Remove the delay for NFC sleep
  2020-12-15  6:53 90% [PATCH v2 net-next 0/2] nfc: s3fwrn5: Refactor the s3fwrn5 module Bongsu Jeon
@ 2020-12-15  6:54 90% ` Bongsu Jeon
  2020-12-15  6:54 88% ` [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove unused NCI prop commands Bongsu Jeon
  1 sibling, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-15  6:54 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Remove the delay for NFC sleep because the delay is only needed to
guarantee that the NFC is awake.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/phy_common.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/nfc/s3fwrn5/phy_common.c b/drivers/nfc/s3fwrn5/phy_common.c
index 497b02b30ae7..81318478d5fd 100644
--- a/drivers/nfc/s3fwrn5/phy_common.c
+++ b/drivers/nfc/s3fwrn5/phy_common.c
@@ -20,7 +20,8 @@ void s3fwrn5_phy_set_wake(void *phy_id, bool wake)
 
 	mutex_lock(&phy->mutex);
 	gpio_set_value(phy->gpio_fw_wake, wake);
-	msleep(S3FWRN5_EN_WAIT_TIME);
+	if (wake)
+		msleep(S3FWRN5_EN_WAIT_TIME);
 	mutex_unlock(&phy->mutex);
 }
 EXPORT_SYMBOL(s3fwrn5_phy_set_wake);
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove unused NCI prop commands
  2020-12-15  6:53 90% [PATCH v2 net-next 0/2] nfc: s3fwrn5: Refactor the s3fwrn5 module Bongsu Jeon
  2020-12-15  6:54 90% ` [PATCH v2 net-next 1/2] nfc: s3fwrn5: Remove the delay for NFC sleep Bongsu Jeon
@ 2020-12-15  6:54 88% ` Bongsu Jeon
  1 sibling, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-15  6:54 UTC (permalink / raw)
  To: krzk; +Cc: linux-nfc, netdev, linux-kernel, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Remove the unused NCI prop commands that s3fwrn5 driver doesn't use.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/s3fwrn5/nci.c | 25 -------------------------
 drivers/nfc/s3fwrn5/nci.h | 22 ----------------------
 2 files changed, 47 deletions(-)

diff --git a/drivers/nfc/s3fwrn5/nci.c b/drivers/nfc/s3fwrn5/nci.c
index 103bf5c92bdc..f042d3eaf8f6 100644
--- a/drivers/nfc/s3fwrn5/nci.c
+++ b/drivers/nfc/s3fwrn5/nci.c
@@ -21,31 +21,11 @@ static int s3fwrn5_nci_prop_rsp(struct nci_dev *ndev, struct sk_buff *skb)
 }
 
 static struct nci_driver_ops s3fwrn5_nci_prop_ops[] = {
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_AGAIN),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_GET_RFREG),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
 	{
 		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
 				NCI_PROP_SET_RFREG),
 		.rsp = s3fwrn5_nci_prop_rsp,
 	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_GET_RFREG_VER),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_SET_RFREG_VER),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
 	{
 		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
 				NCI_PROP_START_RFREG),
@@ -61,11 +41,6 @@ static struct nci_driver_ops s3fwrn5_nci_prop_ops[] = {
 				NCI_PROP_FW_CFG),
 		.rsp = s3fwrn5_nci_prop_rsp,
 	},
-	{
-		.opcode = nci_opcode_pack(NCI_GID_PROPRIETARY,
-				NCI_PROP_WR_RESET),
-		.rsp = s3fwrn5_nci_prop_rsp,
-	},
 };
 
 void s3fwrn5_nci_get_prop_ops(struct nci_driver_ops **ops, size_t *n)
diff --git a/drivers/nfc/s3fwrn5/nci.h b/drivers/nfc/s3fwrn5/nci.h
index 23c0b28f247a..a80f0fb082a8 100644
--- a/drivers/nfc/s3fwrn5/nci.h
+++ b/drivers/nfc/s3fwrn5/nci.h
@@ -11,9 +11,6 @@
 
 #include "s3fwrn5.h"
 
-#define NCI_PROP_AGAIN		0x01
-
-#define NCI_PROP_GET_RFREG	0x21
 #define NCI_PROP_SET_RFREG	0x22
 
 struct nci_prop_set_rfreg_cmd {
@@ -25,23 +22,6 @@ struct nci_prop_set_rfreg_rsp {
 	__u8 status;
 };
 
-#define NCI_PROP_GET_RFREG_VER	0x24
-
-struct nci_prop_get_rfreg_ver_rsp {
-	__u8 status;
-	__u8 data[8];
-};
-
-#define NCI_PROP_SET_RFREG_VER	0x25
-
-struct nci_prop_set_rfreg_ver_cmd {
-	__u8 data[8];
-};
-
-struct nci_prop_set_rfreg_ver_rsp {
-	__u8 status;
-};
-
 #define NCI_PROP_START_RFREG	0x26
 
 struct nci_prop_start_rfreg_rsp {
@@ -70,8 +50,6 @@ struct nci_prop_fw_cfg_rsp {
 	__u8 status;
 };
 
-#define NCI_PROP_WR_RESET	0x2f
-
 void s3fwrn5_nci_get_prop_ops(struct nci_driver_ops **ops, size_t *n);
 int s3fwrn5_nci_rf_configure(struct s3fwrn5_info *info, const char *fw_name);
 
-- 
2.17.1


^ permalink raw reply related	[relevance 88%]

* [PATCH net-next] net: nfc: nci: Change the NCI close sequence
@ 2020-12-28  1:46 90% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-28  1:46 UTC (permalink / raw)
  To: davem, kuba; +Cc: netdev, linux-kernel, linux-nfc, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Change the NCI close sequence because the NCI Command timer should be
deleted after flushing the NCI command work queue.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 net/nfc/nci/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index e64727e1a72f..79bebf4b0796 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -579,11 +579,11 @@ static int nci_close_device(struct nci_dev *ndev)
 
 	clear_bit(NCI_INIT, &ndev->flags);
 
-	del_timer_sync(&ndev->cmd_timer);
-
 	/* Flush cmd wq */
 	flush_workqueue(ndev->cmd_wq);
 
+	del_timer_sync(&ndev->cmd_timer);
+
 	/* Clear flags */
 	ndev->flags = 0;
 
-- 
2.17.1


^ permalink raw reply related	[relevance 90%]

* [PATCH net-next] nfc: Add a virtual nci device driver
@ 2020-12-28  9:45 71% Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-28  9:45 UTC (permalink / raw)
  To: davem, kuba; +Cc: netdev, linux-kernel, linux-nfc, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

A NCI virtual device can be made to simulate a NCI device in user space.
Using the virtual NCI device, The NCI module and application can be
validated. This driver supports to communicate between the virtual NCI
device and NCI module.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 MAINTAINERS                  |   7 ++
 drivers/nfc/Kconfig          |  11 ++
 drivers/nfc/Makefile         |   1 +
 drivers/nfc/virtual_ncidev.c | 216 +++++++++++++++++++++++++++++++++++
 4 files changed, 235 insertions(+)
 create mode 100644 drivers/nfc/virtual_ncidev.c

diff --git a/MAINTAINERS b/MAINTAINERS
index a355db292486..6479a4754a1e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12431,6 +12431,13 @@ F:	include/net/nfc/
 F:	include/uapi/linux/nfc.h
 F:	net/nfc/
 
+NFC VIRTUAL NCI DEVICE DRIVER
+M:	Bongsu Jeon <bongsu.jeon@samsung.com>
+L:	netdev@vger.kernel.org
+L:	linux-nfc@lists.01.org (moderated for non-subscribers)
+S:	Supported
+F:	drivers/nfc/virtual_ncidev.c
+
 NFS, SUNRPC, AND LOCKD CLIENTS
 M:	Trond Myklebust <trond.myklebust@hammerspace.com>
 M:	Anna Schumaker <anna.schumaker@netapp.com>
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 75c65d339018..d32c3a8937ed 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -49,6 +49,17 @@ config NFC_PORT100
 
 	  If unsure, say N.
 
+config NFC_VIRTUAL_NCI
+	tristate "NCI device simulator driver"
+	depends on NFC_NCI
+	help
+	  A NCI virtual device can be made to simulate a NCI device in user
+	  level. Using the virtual NCI device, The NCI module and application
+	  can be validated. This driver supports to communicate between the
+	  virtual NCI device and NCI module.
+
+	  If unsure, say N.
+
 source "drivers/nfc/fdp/Kconfig"
 source "drivers/nfc/pn544/Kconfig"
 source "drivers/nfc/pn533/Kconfig"
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 5393ba59b17d..7b1bfde1d971 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_NFC_ST_NCI)	+= st-nci/
 obj-$(CONFIG_NFC_NXP_NCI)	+= nxp-nci/
 obj-$(CONFIG_NFC_S3FWRN5)	+= s3fwrn5/
 obj-$(CONFIG_NFC_ST95HF)	+= st95hf/
+obj-$(CONFIG_NFC_VIRTUAL_NCI)	+= virtual_ncidev.o
diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c
new file mode 100644
index 000000000000..163d0b2dda2e
--- /dev/null
+++ b/drivers/nfc/virtual_ncidev.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Virtual NCI device simulation driver
+ *
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <net/nfc/nci_core.h>
+
+enum virtual_ncidev_mode {
+	virtual_ncidev_enabled,
+	virtual_ncidev_disabled,
+	virtual_ncidev_disabling,
+};
+
+#define VIRTUAL_NFC_PROTOCOLS	(NFC_PROTO_JEWEL_MASK | \
+				 NFC_PROTO_MIFARE_MASK | \
+				 NFC_PROTO_FELICA_MASK | \
+				 NFC_PROTO_ISO14443_MASK | \
+				 NFC_PROTO_ISO14443_B_MASK | \
+				 NFC_PROTO_ISO15693_MASK)
+
+static enum virtual_ncidev_mode state;
+static struct mutex nci_send_mutex;
+static struct miscdevice miscdev;
+static struct sk_buff *send_buff;
+static struct mutex nci_mutex;
+static struct nci_dev *ndev;
+static bool full_txbuff;
+
+static bool virtual_ncidev_check_enabled(void)
+{
+	bool ret = true;
+
+	mutex_lock(&nci_mutex);
+	if (state != virtual_ncidev_enabled)
+		ret = false;
+	mutex_unlock(&nci_mutex);
+
+	return ret;
+}
+
+static int virtual_nci_open(struct nci_dev *ndev)
+{
+	return 0;
+}
+
+static int virtual_nci_close(struct nci_dev *ndev)
+{
+	mutex_lock(&nci_send_mutex);
+	if (full_txbuff)
+		kfree_skb(send_buff);
+	full_txbuff = false;
+	mutex_unlock(&nci_send_mutex);
+
+	return 0;
+}
+
+static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	if (virtual_ncidev_check_enabled() == false)
+		return 0;
+
+	mutex_lock(&nci_send_mutex);
+	if (full_txbuff) {
+		mutex_unlock(&nci_send_mutex);
+		return -1;
+	}
+	send_buff = skb_copy(skb, GFP_KERNEL);
+	full_txbuff = true;
+	mutex_unlock(&nci_send_mutex);
+
+	return 0;
+}
+
+static struct nci_ops virtual_nci_ops = {
+	.open = virtual_nci_open,
+	.close = virtual_nci_close,
+	.send = virtual_nci_send
+};
+
+static ssize_t virtual_ncidev_read(struct file *file, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	size_t actual_len;
+
+	mutex_lock(&nci_send_mutex);
+	if (!full_txbuff) {
+		mutex_unlock(&nci_send_mutex);
+		return 0;
+	}
+
+	actual_len = count > send_buff->len ? send_buff->len : count;
+
+	if (copy_to_user(buf, send_buff->data, actual_len)) {
+		mutex_unlock(&nci_send_mutex);
+		return -EFAULT;
+	}
+
+	skb_pull(send_buff, actual_len);
+	if (send_buff->len == 0) {
+		kfree_skb(send_buff);
+		full_txbuff = false;
+	}
+	mutex_unlock(&nci_send_mutex);
+
+	return actual_len;
+}
+
+static ssize_t virtual_ncidev_write(struct file *file,
+				    const char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(count, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	if (copy_from_user(skb_put(skb, count), buf, count))
+		return -EFAULT;
+
+	nci_recv_frame(ndev, skb);
+
+	return count;
+}
+
+static int virtual_ncidev_open(struct inode *inode, struct file *file)
+{
+	int ret = 0;
+
+	mutex_lock(&nci_mutex);
+	if (state != virtual_ncidev_disabled) {
+		mutex_unlock(&nci_mutex);
+		return -EBUSY;
+	}
+
+	mutex_init(&nci_send_mutex);
+
+	ndev = nci_allocate_device(&virtual_nci_ops, VIRTUAL_NFC_PROTOCOLS,
+				   0, 0);
+	if (!ndev) {
+		mutex_unlock(&nci_mutex);
+		return -ENOMEM;
+	}
+
+	ret = nci_register_device(ndev);
+	if (ret < 0) {
+		nci_free_device(ndev);
+		mutex_unlock(&nci_mutex);
+		return ret;
+	}
+	state = virtual_ncidev_enabled;
+	mutex_unlock(&nci_mutex);
+
+	return 0;
+}
+
+static int virtual_ncidev_close(struct inode *inode, struct file *file)
+{
+	mutex_lock(&nci_mutex);
+
+	if (state == virtual_ncidev_enabled) {
+		state = virtual_ncidev_disabling;
+		mutex_unlock(&nci_mutex);
+
+		nci_unregister_device(ndev);
+		nci_free_device(ndev);
+
+		mutex_lock(&nci_mutex);
+	}
+
+	state = virtual_ncidev_disabled;
+	mutex_unlock(&nci_mutex);
+
+	return 0;
+}
+
+static const struct file_operations virtual_ncidev_fops = {
+	.owner = THIS_MODULE,
+	.read = virtual_ncidev_read,
+	.write = virtual_ncidev_write,
+	.open = virtual_ncidev_open,
+	.release = virtual_ncidev_close,
+};
+
+static int __init virtual_ncidev_init(void)
+{
+	int ret;
+
+	mutex_init(&nci_mutex);
+	state = virtual_ncidev_disabled;
+	miscdev.minor = MISC_DYNAMIC_MINOR;
+	miscdev.name = "virtual_nci";
+	miscdev.fops = &virtual_ncidev_fops;
+	ret = misc_register(&miscdev);
+
+	return ret;
+}
+
+static void __exit virtual_ncidev_exit(void)
+{
+	misc_deregister(&miscdev);
+}
+
+module_init(virtual_ncidev_init);
+module_exit(virtual_ncidev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Virtual NCI device simulation driver");
+MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
-- 
2.17.1


^ permalink raw reply related	[relevance 71%]

* [PATCH net-next v2] net: nfc: nci: Change the NCI close sequence
@ 2020-12-31  2:59 89% Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2020-12-31  2:59 UTC (permalink / raw)
  To: davem, kuba; +Cc: netdev, linux-kernel, linux-nfc, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

If there is a NCI command in work queue after closing the NCI device at 
nci_unregister_device, The NCI command timer starts at flush_workqueue
function and then NCI command timeout handler would be called 5 second 
after flushing the NCI command work queue and destroying the queue.
At that time, the timeout handler would try to use NCI command work queue
that is destroyed already. it will causes the problem. To avoid this 
abnormal situation, change the sequence to prevent the NCI command timeout
handler from being called after destroying the NCI command work queue.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---

Changes in v2:
 - Change the commit message.

 net/nfc/nci/core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index e64727e1a72f..79bebf4b0796 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -579,11 +579,11 @@ static int nci_close_device(struct nci_dev *ndev)
 
 	clear_bit(NCI_INIT, &ndev->flags);
 
-	del_timer_sync(&ndev->cmd_timer);
-
 	/* Flush cmd wq */
 	flush_workqueue(ndev->cmd_wq);
 
+	del_timer_sync(&ndev->cmd_timer);
+
 	/* Clear flags */
 	ndev->flags = 0;
 
-- 
2.17.1


^ permalink raw reply related	[relevance 89%]

* Re: [PATCH net-next] nfc: Add a virtual nci device driver
  @ 2020-12-31  5:22 90%   ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2020-12-31  5:22 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: davem, netdev, linux-kernel, linux-nfc, Bongsu Jeon

On Tue, Dec 29, 2020 at 6:16 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Mon, 28 Dec 2020 18:45:07 +0900 Bongsu Jeon wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > A NCI virtual device can be made to simulate a NCI device in user space.
> > Using the virtual NCI device, The NCI module and application can be
> > validated. This driver supports to communicate between the virtual NCI
> > device and NCI module.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
>
> net-next is still closed:
>
> http://vger.kernel.org/~davem/net-next.html
>
> Please repost in a few days.
>
> As far as the patch goes - please include some tests for the NCI/NFC
> subsystem based on this virtual device, best if they live in tree under
> tools/testing/selftest.

thank you for your answer.
I think that neard(NFC deamon) is necessary to test the NCI subsystem
meaningfully.
The NCI virtual device in user space can communicate with neard
through this driver.
Is it enough to make NCI virtual device at tools/nfc for some test?

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next] nfc: Add a virtual nci device driver
  @ 2021-01-05 23:16 90%       ` Bongsu Jeon
    0 siblings, 1 reply; 79+ results
From: Bongsu Jeon @ 2021-01-05 23:16 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: davem, netdev, linux-kernel, linux-nfc, Bongsu Jeon

On Tue, Jan 5, 2021 at 4:48 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Thu, 31 Dec 2020 14:22:45 +0900 Bongsu Jeon wrote:
> > On Tue, Dec 29, 2020 at 6:16 AM Jakub Kicinski <kuba@kernel.org> wrote:
> > >
> > > On Mon, 28 Dec 2020 18:45:07 +0900 Bongsu Jeon wrote:
> > > > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> > > >
> > > > A NCI virtual device can be made to simulate a NCI device in user space.
> > > > Using the virtual NCI device, The NCI module and application can be
> > > > validated. This driver supports to communicate between the virtual NCI
> > > > device and NCI module.
> > > >
> > > > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> > >
> > > net-next is still closed:
> > >
> > > http://vger.kernel.org/~davem/net-next.html
> > >
> > > Please repost in a few days.
> > >
> > > As far as the patch goes - please include some tests for the NCI/NFC
> > > subsystem based on this virtual device, best if they live in tree under
> > > tools/testing/selftest.
> >
> > thank you for your answer.
> > I think that neard(NFC deamon) is necessary to test the NCI subsystem
> > meaningfully.
> > The NCI virtual device in user space can communicate with neard
> > through this driver.
> > Is it enough to make NCI virtual device at tools/nfc for some test?
>
> I'm not sure if I understand. Are you asking if it's okay for the test
> or have a dependency on neard?

Sorry for confusing you.
There is no dependency between neard and a NCI virtual device.
But, To test the NCI module, it is necessary to make an application like neard.
Is it okay to just make a NCI virtual device as a tool at tools/nfc
without the application?

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net-next] nfc: Add a virtual nci device driver
  @ 2021-01-07 22:38 90%           ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-01-07 22:38 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: davem, netdev, linux-kernel, linux-nfc, Bongsu Jeon

On Thu, Jan 7, 2021 at 2:01 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed, 6 Jan 2021 08:16:47 +0900 Bongsu Jeon wrote:
> > On Tue, Jan 5, 2021 at 4:48 AM Jakub Kicinski <kuba@kernel.org> wrote:
> > > > thank you for your answer.
> > > > I think that neard(NFC deamon) is necessary to test the NCI subsystem
> > > > meaningfully.
> > > > The NCI virtual device in user space can communicate with neard
> > > > through this driver.
> > > > Is it enough to make NCI virtual device at tools/nfc for some test?
> > >
> > > I'm not sure if I understand. Are you asking if it's okay for the test
> > > or have a dependency on neard?
> >
> > Sorry for confusing you.
> > There is no dependency between neard and a NCI virtual device.
> > But, To test the NCI module, it is necessary to make an application like neard.
> > Is it okay to just make a NCI virtual device as a tool at tools/nfc
> > without the application?
>
> Meaning the device will be created but there will be no test cases in
> the tree?

yes.

>
> What we'd like to see is some form of a test which would exercise the
> NFC-related kernel code on such a device and can signal success /
> failure. It doesn't have to be very complex.
>
> You can build a more complex user space applications and tests
> separately.

okay. I understand it. I will try to make it.

^ permalink raw reply	[relevance 90%]

* [PATCH net] net: nfc: nci: fix the wrong NCI_CORE_INIT parameters
@ 2021-01-18 20:55 90% Bongsu Jeon
      0 siblings, 2 replies; 79+ results
From: Bongsu Jeon @ 2021-01-18 20:55 UTC (permalink / raw)
  To: davem, kuba; +Cc: netdev, linux-kernel, linux-nfc, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

Fix the code because NCI_CORE_INIT_CMD includes two parameters in NCI2.0
but there is no parameters in NCI1.x.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 net/nfc/nci/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index e64727e1a72f..02a1f13f0798 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -508,7 +508,7 @@ static int nci_open_device(struct nci_dev *ndev)
 		};
 		unsigned long opt = 0;
 
-		if (!(ndev->nci_ver & NCI_VER_2_MASK))
+		if (ndev->nci_ver & NCI_VER_2_MASK)
 			opt = (unsigned long)&nci_init_v2_cmd;
 
 		rc = __nci_request(ndev, nci_init_req, opt,
-- 
2.25.1


^ permalink raw reply related	[relevance 90%]

* Re: [PATCH net] net: nfc: nci: fix the wrong NCI_CORE_INIT parameters
  @ 2021-01-18 21:19 90%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-01-18 21:19 UTC (permalink / raw)
  To: Jakub Kicinski; +Cc: davem, netdev, linux-kernel, linux-nfc, Bongsu Jeon

On Tue, Jan 19, 2021 at 6:01 AM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Tue, 19 Jan 2021 05:55:22 +0900 Bongsu Jeon wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > Fix the code because NCI_CORE_INIT_CMD includes two parameters in NCI2.0
> > but there is no parameters in NCI1.x.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
>
> What's the Fixes tag for this change?
Sorry to miss the Fixes tag.
This is the Fixes tag ( Fixes: bcd684aace34 ("net/nfc/nci: Support NCI
2.x initial sequence") )
Could I resend this patch after adding that tag?

^ permalink raw reply	[relevance 90%]

* Re: [PATCH net] net: nfc: nci: fix the wrong NCI_CORE_INIT parameters
  @ 2021-01-20  9:54 90%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-01-20  9:54 UTC (permalink / raw)
  To: patchwork-bot+netdevbpf
  Cc: davem, Jakub Kicinski, netdev, linux-kernel, linux-nfc, Bongsu Jeon

On Wed, Jan 20, 2021 at 10:00 AM <patchwork-bot+netdevbpf@kernel.org> wrote:
>
> Hello:
>
> This patch was applied to netdev/net.git (refs/heads/master):
>
> On Tue, 19 Jan 2021 05:55:22 +0900 you wrote:
> > From: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > Fix the code because NCI_CORE_INIT_CMD includes two parameters in NCI2.0
> > but there is no parameters in NCI1.x.
> >
> > Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
> >
> > [...]
>
> Here is the summary with links:
>   - [net] net: nfc: nci: fix the wrong NCI_CORE_INIT parameters
>     https://git.kernel.org/netdev/net/c/4964e5a1e080
>
> You are awesome, thank you!
> --
> Deet-doot-dot, I am a bot.
> https://korg.docs.kernel.org/patchwork/pwbot.html
>
>

Could you merge this patch to net-next repo??
NCI selftest that i will send will fail if this patch isn't merged.

^ permalink raw reply	[relevance 90%]

* [PATCH net-next v4 0/2] Add nci suit and virtual nci device driver
@ 2021-01-27 13:08 89% Bongsu Jeon
  2021-01-27 13:08 73% ` [PATCH net-next v4 1/2] nfc: Add a " Bongsu Jeon
  2021-01-27 13:08 50% ` [PATCH net-next v4 2/2] selftests: Add nci suite Bongsu Jeon
  0 siblings, 2 replies; 79+ results
From: Bongsu Jeon @ 2021-01-27 13:08 UTC (permalink / raw)
  To: kuba, shuah
  Cc: krzk, linux-kernel, netdev, linux-nfc, linux-kselftest, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

1/2 is the Virtual NCI device driver.
2/2 is the NCI selftest suite

v4:
 1/2
 - flip the condition for the ioctl.
 - refactor some code.
 - remove the unused function after refactoring.
v3:
 1/2
 - change the Kconfig help comment.
 - remove the mutex init code.
 - remove the unnecessary mutex(nci_send_mutex).
 - remove the full_txbuff.
 - add the code to release skb at error case.
 - refactor some code.
v2:
 1/2
 - change the permission of the Virtual NCI device.
 - add the ioctl to find the nci device index.
 2/2
 - add the NCI selftest suite.

Bongsu Jeon (2):
  nfc: Add a virtual nci device driver
  selftests: Add nci suite

 MAINTAINERS                           |   8 +
 drivers/nfc/Kconfig                   |  11 +
 drivers/nfc/Makefile                  |   1 +
 drivers/nfc/virtual_ncidev.c          | 215 +++++++++
 tools/testing/selftests/Makefile      |   1 +
 tools/testing/selftests/nci/Makefile  |   6 +
 tools/testing/selftests/nci/config    |   3 +
 tools/testing/selftests/nci/nci_dev.c | 599 ++++++++++++++++++++++++++
 8 files changed, 844 insertions(+)
 create mode 100644 drivers/nfc/virtual_ncidev.c
 create mode 100644 tools/testing/selftests/nci/Makefile
 create mode 100644 tools/testing/selftests/nci/config
 create mode 100644 tools/testing/selftests/nci/nci_dev.c

-- 
2.25.1


^ permalink raw reply	[relevance 89%]

* [PATCH net-next v4 1/2] nfc: Add a virtual nci device driver
  2021-01-27 13:08 89% [PATCH net-next v4 0/2] Add nci suit and virtual nci device driver Bongsu Jeon
@ 2021-01-27 13:08 73% ` Bongsu Jeon
  2021-01-27 13:08 50% ` [PATCH net-next v4 2/2] selftests: Add nci suite Bongsu Jeon
  1 sibling, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-01-27 13:08 UTC (permalink / raw)
  To: kuba, shuah
  Cc: krzk, linux-kernel, netdev, linux-nfc, linux-kselftest, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

NCI virtual device simulates a NCI device to the user. It can be used to
validate the NCI module and applications. This driver supports
communication between the virtual NCI device and NCI module.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 drivers/nfc/Kconfig          |  11 ++
 drivers/nfc/Makefile         |   1 +
 drivers/nfc/virtual_ncidev.c | 215 +++++++++++++++++++++++++++++++++++
 3 files changed, 227 insertions(+)
 create mode 100644 drivers/nfc/virtual_ncidev.c

diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 75c65d339018..288c6f1c6979 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -49,6 +49,17 @@ config NFC_PORT100
 
 	  If unsure, say N.
 
+config NFC_VIRTUAL_NCI
+	tristate "NCI device simulator driver"
+	depends on NFC_NCI
+	help
+	  NCI virtual device simulates a NCI device to the user.
+	  It can be used to validate the NCI module and applications.
+	  This driver supports communication between the virtual NCI device and
+	  module.
+
+	  If unsure, say N.
+
 source "drivers/nfc/fdp/Kconfig"
 source "drivers/nfc/pn544/Kconfig"
 source "drivers/nfc/pn533/Kconfig"
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile
index 5393ba59b17d..7b1bfde1d971 100644
--- a/drivers/nfc/Makefile
+++ b/drivers/nfc/Makefile
@@ -17,3 +17,4 @@ obj-$(CONFIG_NFC_ST_NCI)	+= st-nci/
 obj-$(CONFIG_NFC_NXP_NCI)	+= nxp-nci/
 obj-$(CONFIG_NFC_S3FWRN5)	+= s3fwrn5/
 obj-$(CONFIG_NFC_ST95HF)	+= st95hf/
+obj-$(CONFIG_NFC_VIRTUAL_NCI)	+= virtual_ncidev.o
diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c
new file mode 100644
index 000000000000..f73ee0bf3593
--- /dev/null
+++ b/drivers/nfc/virtual_ncidev.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Virtual NCI device simulation driver
+ *
+ * Copyright (C) 2020 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/miscdevice.h>
+#include <linux/mutex.h>
+#include <net/nfc/nci_core.h>
+
+enum virtual_ncidev_mode {
+	virtual_ncidev_enabled,
+	virtual_ncidev_disabled,
+	virtual_ncidev_disabling,
+};
+
+#define IOCTL_GET_NCIDEV_IDX    0
+#define VIRTUAL_NFC_PROTOCOLS	(NFC_PROTO_JEWEL_MASK | \
+				 NFC_PROTO_MIFARE_MASK | \
+				 NFC_PROTO_FELICA_MASK | \
+				 NFC_PROTO_ISO14443_MASK | \
+				 NFC_PROTO_ISO14443_B_MASK | \
+				 NFC_PROTO_ISO15693_MASK)
+
+static enum virtual_ncidev_mode state;
+static struct miscdevice miscdev;
+static struct sk_buff *send_buff;
+static struct nci_dev *ndev;
+static DEFINE_MUTEX(nci_mutex);
+
+static int virtual_nci_open(struct nci_dev *ndev)
+{
+	return 0;
+}
+
+static int virtual_nci_close(struct nci_dev *ndev)
+{
+	mutex_lock(&nci_mutex);
+	kfree_skb(send_buff);
+	send_buff = NULL;
+	mutex_unlock(&nci_mutex);
+
+	return 0;
+}
+
+static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
+{
+	mutex_lock(&nci_mutex);
+	if (state != virtual_ncidev_enabled) {
+		mutex_unlock(&nci_mutex);
+		return 0;
+	}
+
+	if (send_buff) {
+		mutex_unlock(&nci_mutex);
+		return -1;
+	}
+	send_buff = skb_copy(skb, GFP_KERNEL);
+	mutex_unlock(&nci_mutex);
+
+	return 0;
+}
+
+static struct nci_ops virtual_nci_ops = {
+	.open = virtual_nci_open,
+	.close = virtual_nci_close,
+	.send = virtual_nci_send
+};
+
+static ssize_t virtual_ncidev_read(struct file *file, char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	size_t actual_len;
+
+	mutex_lock(&nci_mutex);
+	if (!send_buff) {
+		mutex_unlock(&nci_mutex);
+		return 0;
+	}
+
+	actual_len = min_t(size_t, count, send_buff->len);
+
+	if (copy_to_user(buf, send_buff->data, actual_len)) {
+		mutex_unlock(&nci_mutex);
+		return -EFAULT;
+	}
+
+	skb_pull(send_buff, actual_len);
+	if (send_buff->len == 0) {
+		consume_skb(send_buff);
+		send_buff = NULL;
+	}
+	mutex_unlock(&nci_mutex);
+
+	return actual_len;
+}
+
+static ssize_t virtual_ncidev_write(struct file *file,
+				    const char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_skb(count, GFP_KERNEL);
+	if (!skb)
+		return -ENOMEM;
+
+	if (copy_from_user(skb_put(skb, count), buf, count)) {
+		kfree_skb(skb);
+		return -EFAULT;
+	}
+
+	nci_recv_frame(ndev, skb);
+	return count;
+}
+
+static int virtual_ncidev_open(struct inode *inode, struct file *file)
+{
+	int ret = 0;
+
+	mutex_lock(&nci_mutex);
+	if (state != virtual_ncidev_disabled) {
+		mutex_unlock(&nci_mutex);
+		return -EBUSY;
+	}
+
+	ndev = nci_allocate_device(&virtual_nci_ops, VIRTUAL_NFC_PROTOCOLS,
+				   0, 0);
+	if (!ndev) {
+		mutex_unlock(&nci_mutex);
+		return -ENOMEM;
+	}
+
+	ret = nci_register_device(ndev);
+	if (ret < 0) {
+		nci_free_device(ndev);
+		mutex_unlock(&nci_mutex);
+		return ret;
+	}
+	state = virtual_ncidev_enabled;
+	mutex_unlock(&nci_mutex);
+
+	return 0;
+}
+
+static int virtual_ncidev_close(struct inode *inode, struct file *file)
+{
+	mutex_lock(&nci_mutex);
+
+	if (state == virtual_ncidev_enabled) {
+		state = virtual_ncidev_disabling;
+		mutex_unlock(&nci_mutex);
+
+		nci_unregister_device(ndev);
+		nci_free_device(ndev);
+
+		mutex_lock(&nci_mutex);
+	}
+
+	state = virtual_ncidev_disabled;
+	mutex_unlock(&nci_mutex);
+
+	return 0;
+}
+
+static long virtual_ncidev_ioctl(struct file *flip, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct nfc_dev *nfc_dev = ndev->nfc_dev;
+	void __user *p = (void __user *)arg;
+
+	if (cmd != IOCTL_GET_NCIDEV_IDX)
+		return -ENOTTY;
+
+	if (copy_to_user(p, &nfc_dev->idx, sizeof(nfc_dev->idx)))
+		return -EFAULT;
+
+	return 0;
+}
+
+static const struct file_operations virtual_ncidev_fops = {
+	.owner = THIS_MODULE,
+	.read = virtual_ncidev_read,
+	.write = virtual_ncidev_write,
+	.open = virtual_ncidev_open,
+	.release = virtual_ncidev_close,
+	.unlocked_ioctl = virtual_ncidev_ioctl
+};
+
+static int __init virtual_ncidev_init(void)
+{
+	state = virtual_ncidev_disabled;
+	miscdev.minor = MISC_DYNAMIC_MINOR;
+	miscdev.name = "virtual_nci";
+	miscdev.fops = &virtual_ncidev_fops;
+	miscdev.mode = S_IALLUGO;
+
+	return misc_register(&miscdev);
+}
+
+static void __exit virtual_ncidev_exit(void)
+{
+	misc_deregister(&miscdev);
+}
+
+module_init(virtual_ncidev_init);
+module_exit(virtual_ncidev_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Virtual NCI device simulation driver");
+MODULE_AUTHOR("Bongsu Jeon <bongsu.jeon@samsung.com>");
-- 
2.25.1


^ permalink raw reply related	[relevance 73%]

* [PATCH net-next v4 2/2] selftests: Add nci suite
  2021-01-27 13:08 89% [PATCH net-next v4 0/2] Add nci suit and virtual nci device driver Bongsu Jeon
  2021-01-27 13:08 73% ` [PATCH net-next v4 1/2] nfc: Add a " Bongsu Jeon
@ 2021-01-27 13:08 50% ` Bongsu Jeon
  1 sibling, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-01-27 13:08 UTC (permalink / raw)
  To: kuba, shuah
  Cc: krzk, linux-kernel, netdev, linux-nfc, linux-kselftest, Bongsu Jeon

From: Bongsu Jeon <bongsu.jeon@samsung.com>

This is the NCI test suite. It tests the NFC/NCI module using virtual NCI
device. Test cases consist of making the virtual NCI device on/off and
controlling the device's polling for NCI1.0 and NCI2.0 version.

Signed-off-by: Bongsu Jeon <bongsu.jeon@samsung.com>
---
 MAINTAINERS                           |   8 +
 tools/testing/selftests/Makefile      |   1 +
 tools/testing/selftests/nci/Makefile  |   6 +
 tools/testing/selftests/nci/config    |   3 +
 tools/testing/selftests/nci/nci_dev.c | 599 ++++++++++++++++++++++++++
 5 files changed, 617 insertions(+)
 create mode 100644 tools/testing/selftests/nci/Makefile
 create mode 100644 tools/testing/selftests/nci/config
 create mode 100644 tools/testing/selftests/nci/nci_dev.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 096b584e7fed..b62832e39e2a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12531,6 +12531,14 @@ F:	include/net/nfc/
 F:	include/uapi/linux/nfc.h
 F:	net/nfc/
 
+NFC VIRTUAL NCI DEVICE DRIVER
+M:	Bongsu Jeon <bongsu.jeon@samsung.com>
+L:	netdev@vger.kernel.org
+L:	linux-nfc@lists.01.org (moderated for non-subscribers)
+S:	Supported
+F:	drivers/nfc/virtual_ncidev.c
+F:	tools/testing/selftests/nci/
+
 NFS, SUNRPC, AND LOCKD CLIENTS
 M:	Trond Myklebust <trond.myklebust@hammerspace.com>
 M:	Anna Schumaker <anna.schumaker@netapp.com>
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 8a917cb4426a..c42aacec5038 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -34,6 +34,7 @@ TARGETS += memory-hotplug
 TARGETS += mincore
 TARGETS += mount
 TARGETS += mqueue
+TARGETS += nci
 TARGETS += net
 TARGETS += net/forwarding
 TARGETS += net/mptcp
diff --git a/tools/testing/selftests/nci/Makefile b/tools/testing/selftests/nci/Makefile
new file mode 100644
index 000000000000..47669a1d6a59
--- /dev/null
+++ b/tools/testing/selftests/nci/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+CFLAGS += -Wl,-no-as-needed -Wall
+LDFLAGS += -lpthread
+
+TEST_GEN_PROGS := nci_dev
+include ../lib.mk
diff --git a/tools/testing/selftests/nci/config b/tools/testing/selftests/nci/config
new file mode 100644
index 000000000000..b084e78276be
--- /dev/null
+++ b/tools/testing/selftests/nci/config
@@ -0,0 +1,3 @@
+CONFIG_NFC=y
+CONFIG_NFC_NCI=y
+CONFIG_NFC_VIRTUAL_NCI=y
diff --git a/tools/testing/selftests/nci/nci_dev.c b/tools/testing/selftests/nci/nci_dev.c
new file mode 100644
index 000000000000..57b505cb1561
--- /dev/null
+++ b/tools/testing/selftests/nci/nci_dev.c
@@ -0,0 +1,599 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2021 Samsung Electrnoics
+ * Bongsu Jeon <bongsu.jeon@samsung.com>
+ *
+ * Test code for nci
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <linux/genetlink.h>
+#include <sys/socket.h>
+#include <linux/nfc.h>
+
+#include "../kselftest_harness.h"
+
+#define GENLMSG_DATA(glh)	((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
+#define GENLMSG_PAYLOAD(glh)	(NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
+#define NLA_DATA(na)		((void *)((char *)(na) + NLA_HDRLEN))
+#define NLA_PAYLOAD(len)	((len) - NLA_HDRLEN)
+
+#define MAX_MSG_SIZE	1024
+
+#define IOCTL_GET_NCIDEV_IDX	0
+#define VIRTUAL_NFC_PROTOCOLS	(NFC_PROTO_JEWEL_MASK | \
+				 NFC_PROTO_MIFARE_MASK | \
+				 NFC_PROTO_FELICA_MASK | \
+				 NFC_PROTO_ISO14443_MASK | \
+				 NFC_PROTO_ISO14443_B_MASK | \
+				 NFC_PROTO_ISO15693_MASK)
+
+const __u8 nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x01};
+const __u8 nci_init_cmd[] = {0x20, 0x01, 0x00};
+const __u8 nci_rf_discovery_cmd[] = {0x21, 0x03, 0x09, 0x04, 0x00, 0x01,
+				      0x01, 0x01, 0x02, 0x01, 0x06, 0x01};
+const __u8 nci_init_cmd_v2[] = {0x20, 0x01, 0x02, 0x00, 0x00};
+const __u8 nci_rf_disc_map_cmd[] = {0x21, 0x00, 0x07, 0x02, 0x04, 0x03,
+				     0x02, 0x05, 0x03, 0x03};
+const __u8 nci_rf_deact_cmd[] = {0x21, 0x06, 0x01, 0x00};
+const __u8 nci_reset_rsp[] = {0x40, 0x00, 0x03, 0x00, 0x10, 0x01};
+const __u8 nci_reset_rsp_v2[] = {0x40, 0x00, 0x01, 0x00};
+const __u8 nci_reset_ntf[] = {0x60, 0x00, 0x09, 0x02, 0x01, 0x20, 0x0e,
+			       0x04, 0x61, 0x00, 0x04, 0x02};
+const __u8 nci_init_rsp[] = {0x40, 0x01, 0x14, 0x00, 0x02, 0x0e, 0x02,
+			      0x00, 0x03, 0x01, 0x02, 0x03, 0x02, 0xc8,
+			      0x00, 0xff, 0x10, 0x00, 0x0e, 0x12, 0x00,
+			      0x00, 0x04};
+const __u8 nci_init_rsp_v2[] = {0x40, 0x01, 0x1c, 0x00, 0x1a, 0x7e, 0x06,
+				 0x00, 0x02, 0x92, 0x04, 0xff, 0xff, 0x01,
+				 0x00, 0x40, 0x06, 0x00, 0x00, 0x01, 0x01,
+				 0x00, 0x02, 0x00, 0x03, 0x01, 0x01, 0x06,
+				 0x00, 0x80, 0x00};
+const __u8 nci_rf_disc_map_rsp[] = {0x41, 0x00, 0x01, 0x00};
+const __u8 nci_rf_disc_rsp[] = {0x41, 0x03, 0x01, 0x00};
+const __u8 nci_rf_deact_rsp[] = {0x41, 0x06, 0x01, 0x00};
+
+struct msgtemplate {
+	struct nlmsghdr n;
+	struct genlmsghdr g;
+	char buf[MAX_MSG_SIZE];
+};
+
+static int create_nl_socket(void)
+{
+	int fd;
+	struct sockaddr_nl local;
+
+	fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+	if (fd < 0)
+		return -1;
+
+	memset(&local, 0, sizeof(local));
+	local.nl_family = AF_NETLINK;
+
+	if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0)
+		goto error;
+
+	return fd;
+error:
+	close(fd);
+	return -1;
+}
+
+static int send_cmd_mt_nla(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
+			   __u8 genl_cmd, int nla_num, __u16 nla_type[],
+			   void *nla_data[], int nla_len[])
+{
+	struct sockaddr_nl nladdr;
+	struct msgtemplate msg;
+	struct nlattr *na;
+	int cnt, prv_len;
+	int r, buflen;
+	char *buf;
+
+	msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
+	msg.n.nlmsg_type = nlmsg_type;
+	msg.n.nlmsg_flags = NLM_F_REQUEST;
+	msg.n.nlmsg_seq = 0;
+	msg.n.nlmsg_pid = nlmsg_pid;
+	msg.g.cmd = genl_cmd;
+	msg.g.version = 0x1;
+
+	prv_len = 0;
+	for (cnt = 0; cnt < nla_num; cnt++) {
+		na = (struct nlattr *)(GENLMSG_DATA(&msg) + prv_len);
+		na->nla_type = nla_type[cnt];
+		na->nla_len = nla_len[cnt] + NLA_HDRLEN;
+
+		if (nla_len > 0)
+			memcpy(NLA_DATA(na), nla_data[cnt], nla_len[cnt]);
+
+		msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
+		prv_len = na->nla_len;
+	}
+
+	buf = (char *)&msg;
+	buflen = msg.n.nlmsg_len;
+	memset(&nladdr, 0, sizeof(nladdr));
+	nladdr.nl_family = AF_NETLINK;
+
+	while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *)&nladdr,
+			   sizeof(nladdr))) < buflen) {
+		if (r > 0) {
+			buf += r;
+			buflen -= r;
+		} else if (errno != EAGAIN) {
+			return -1;
+		}
+	}
+	return 0;
+}
+
+static int send_get_nfc_family(int sd, __u32 pid)
+{
+	__u16 nla_get_family_type = CTRL_ATTR_FAMILY_NAME;
+	void *nla_get_family_data;
+	int nla_get_family_len;
+	char family_name[100];
+
+	nla_get_family_len = strlen(NFC_GENL_NAME) + 1;
+	strcpy(family_name, NFC_GENL_NAME);
+	nla_get_family_data = family_name;
+
+	return send_cmd_mt_nla(sd, GENL_ID_CTRL, pid, CTRL_CMD_GETFAMILY,
+				1, &nla_get_family_type,
+				&nla_get_family_data, &nla_get_family_len);
+}
+
+static int get_family_id(int sd, __u32 pid)
+{
+	struct {
+		struct nlmsghdr n;
+		struct genlmsghdr g;
+		char buf[512];
+	} ans;
+	struct nlattr *na;
+	int rep_len;
+	__u16 id;
+	int rc;
+
+	rc = send_get_nfc_family(sd, pid);
+
+	if (rc < 0)
+		return 0;
+
+	rep_len = recv(sd, &ans, sizeof(ans), 0);
+
+	if (ans.n.nlmsg_type == NLMSG_ERROR || rep_len < 0 ||
+	    !NLMSG_OK(&ans.n, rep_len))
+		return 0;
+
+	na = (struct nlattr *)GENLMSG_DATA(&ans);
+	na = (struct nlattr *)((char *)na + NLA_ALIGN(na->nla_len));
+	if (na->nla_type == CTRL_ATTR_FAMILY_ID)
+		id = *(__u16 *)NLA_DATA(na);
+
+	return id;
+}
+
+static int send_cmd_with_idx(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
+			     __u8 genl_cmd, int dev_id)
+{
+	__u16 nla_type = NFC_ATTR_DEVICE_INDEX;
+	void *nla_data = &dev_id;
+	int nla_len = 4;
+
+	return send_cmd_mt_nla(sd, nlmsg_type, nlmsg_pid, genl_cmd, 1,
+				&nla_type, &nla_data, &nla_len);
+}
+
+static int get_nci_devid(int sd, __u16 fid, __u32 pid, int dev_id, struct msgtemplate *msg)
+{
+	int rc, rep_len;
+
+	rc = send_cmd_with_idx(sd, fid, pid, NFC_CMD_GET_DEVICE, dev_id);
+	if (rc < 0) {
+		rc = -1;
+		goto error;
+	}
+
+	rep_len = recv(sd, msg, sizeof(*msg), 0);
+	if (rep_len < 0) {
+		rc = -2;
+		goto error;
+	}
+
+	if (msg->n.nlmsg_type == NLMSG_ERROR ||
+	    !NLMSG_OK(&msg->n, rep_len)) {
+		rc = -3;
+		goto error;
+	}
+
+	return 0;
+error:
+	return rc;
+}
+
+static __u8 get_dev_enable_state(struct msgtemplate *msg)
+{
+	struct nlattr *na;
+	int rep_len;
+	int len;
+
+	rep_len = GENLMSG_PAYLOAD(&msg->n);
+	na = (struct nlattr *)GENLMSG_DATA(msg);
+	len = 0;
+
+	while (len < rep_len) {
+		len += NLA_ALIGN(na->nla_len);
+		if (na->nla_type == NFC_ATTR_DEVICE_POWERED)
+			return *(char *)NLA_DATA(na);
+		na = (struct nlattr *)(GENLMSG_DATA(msg) + len);
+	}
+
+	return rep_len;
+}
+
+FIXTURE(NCI) {
+	int virtual_nci_fd;
+	bool open_state;
+	int dev_idex;
+	bool isNCI2;
+	int proto;
+	__u32 pid;
+	__u16 fid;
+	int sd;
+};
+
+FIXTURE_VARIANT(NCI) {
+	bool isNCI2;
+};
+
+FIXTURE_VARIANT_ADD(NCI, NCI1_0) {
+	.isNCI2 = false,
+};
+
+FIXTURE_VARIANT_ADD(NCI, NCI2_0) {
+	.isNCI2 = true,
+};
+
+static void *virtual_dev_open(void *data)
+{
+	char buf[258];
+	int dev_fd;
+	int len;
+
+	dev_fd = *(int *)data;
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_reset_cmd))
+		goto error;
+	if (memcmp(nci_reset_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_reset_rsp, sizeof(nci_reset_rsp));
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_init_cmd))
+		goto error;
+	if (memcmp(nci_init_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_init_rsp, sizeof(nci_init_rsp));
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_rf_disc_map_cmd))
+		goto error;
+	if (memcmp(nci_rf_disc_map_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_rf_disc_map_rsp, sizeof(nci_rf_disc_map_rsp));
+
+	return (void *)0;
+error:
+	return (void *)-1;
+}
+
+static void *virtual_dev_open_v2(void *data)
+{
+	char buf[258];
+	int dev_fd;
+	int len;
+
+	dev_fd = *(int *)data;
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_reset_cmd))
+		goto error;
+	if (memcmp(nci_reset_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_reset_rsp_v2, sizeof(nci_reset_rsp_v2));
+	write(dev_fd, nci_reset_ntf, sizeof(nci_reset_ntf));
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_init_cmd_v2))
+		goto error;
+	if (memcmp(nci_init_cmd_v2, buf, len))
+		goto error;
+	write(dev_fd, nci_init_rsp_v2, sizeof(nci_init_rsp_v2));
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_rf_disc_map_cmd))
+		goto error;
+	if (memcmp(nci_rf_disc_map_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_rf_disc_map_rsp, sizeof(nci_rf_disc_map_rsp));
+
+	return (void *)0;
+error:
+	return (void *)-1;
+}
+
+FIXTURE_SETUP(NCI)
+{
+	struct msgtemplate msg;
+	pthread_t thread_t;
+	int status;
+	int rc;
+
+	self->open_state = false;
+	self->proto = VIRTUAL_NFC_PROTOCOLS;
+	self->isNCI2 = variant->isNCI2;
+
+	self->sd = create_nl_socket();
+	ASSERT_NE(self->sd, -1);
+
+	self->pid = getpid();
+	self->fid = get_family_id(self->sd, self->pid);
+	ASSERT_NE(self->fid, -1);
+
+	self->virtual_nci_fd = open("/dev/virtual_nci", O_RDWR);
+	ASSERT_GT(self->virtual_nci_fd, -1);
+
+	rc = ioctl(self->virtual_nci_fd, IOCTL_GET_NCIDEV_IDX, &self->dev_idex);
+	ASSERT_EQ(rc, 0);
+
+	rc = get_nci_devid(self->sd, self->fid, self->pid, self->dev_idex, &msg);
+	ASSERT_EQ(rc, 0);
+	EXPECT_EQ(get_dev_enable_state(&msg), 0);
+
+	if (self->isNCI2)
+		rc = pthread_create(&thread_t, NULL, virtual_dev_open_v2,
+				    (void *)&self->virtual_nci_fd);
+	else
+		rc = pthread_create(&thread_t, NULL, virtual_dev_open,
+				    (void *)&self->virtual_nci_fd);
+	ASSERT_GT(rc, -1);
+
+	rc = send_cmd_with_idx(self->sd, self->fid, self->pid,
+			       NFC_CMD_DEV_UP, self->dev_idex);
+	EXPECT_EQ(rc, 0);
+
+	pthread_join(thread_t, (void **)&status);
+	ASSERT_EQ(status, 0);
+	self->open_state = true;
+}
+
+static void *virtual_deinit(void *data)
+{
+	char buf[258];
+	int dev_fd;
+	int len;
+
+	dev_fd = *(int *)data;
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_reset_cmd))
+		goto error;
+	if (memcmp(nci_reset_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_reset_rsp, sizeof(nci_reset_rsp));
+
+	return (void *)0;
+error:
+	return (void *)-1;
+}
+
+static void *virtual_deinit_v2(void *data)
+{
+	char buf[258];
+	int dev_fd;
+	int len;
+
+	dev_fd = *(int *)data;
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_reset_cmd))
+		goto error;
+	if (memcmp(nci_reset_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_reset_rsp_v2, sizeof(nci_reset_rsp_v2));
+	write(dev_fd, nci_reset_ntf, sizeof(nci_reset_ntf));
+
+	return (void *)0;
+error:
+	return (void *)-1;
+}
+
+FIXTURE_TEARDOWN(NCI)
+{
+	pthread_t thread_t;
+	int status;
+	int rc;
+
+	if (self->open_state) {
+		if (self->isNCI2)
+			rc = pthread_create(&thread_t, NULL,
+					    virtual_deinit_v2,
+					    (void *)&self->virtual_nci_fd);
+		else
+			rc = pthread_create(&thread_t, NULL, virtual_deinit,
+					    (void *)&self->virtual_nci_fd);
+
+		ASSERT_GT(rc, -1);
+		rc = send_cmd_with_idx(self->sd, self->fid, self->pid,
+				       NFC_CMD_DEV_DOWN, self->dev_idex);
+		EXPECT_EQ(rc, 0);
+
+		pthread_join(thread_t, (void **)&status);
+		ASSERT_EQ(status, 0);
+	}
+
+	close(self->sd);
+	close(self->virtual_nci_fd);
+	self->open_state = false;
+}
+
+TEST_F(NCI, init)
+{
+	struct msgtemplate msg;
+	int rc;
+
+	rc = get_nci_devid(self->sd, self->fid, self->pid, self->dev_idex,
+			   &msg);
+	ASSERT_EQ(rc, 0);
+	EXPECT_EQ(get_dev_enable_state(&msg), 1);
+}
+
+static void *virtual_poll_start(void *data)
+{
+	char buf[258];
+	int dev_fd;
+	int len;
+
+	dev_fd = *(int *)data;
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_rf_discovery_cmd))
+		goto error;
+	if (memcmp(nci_rf_discovery_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_rf_disc_rsp, sizeof(nci_rf_disc_rsp))
+		;
+
+	return (void *)0;
+error:
+	return (void *)-1;
+}
+
+static void *virtual_poll_stop(void *data)
+{
+	char buf[258];
+	int dev_fd;
+	int len;
+
+	dev_fd = *(int *)data;
+
+	while ((len = read(dev_fd, buf, 258)) == 0)
+		;
+	if (len <= 0)
+		goto error;
+	if (len != sizeof(nci_rf_deact_cmd))
+		goto error;
+	if (memcmp(nci_rf_deact_cmd, buf, len))
+		goto error;
+	write(dev_fd, nci_rf_deact_rsp, sizeof(nci_rf_deact_rsp));
+
+	return (void *)0;
+error:
+	return (void *)-1;
+}
+
+TEST_F(NCI, start_poll)
+{
+	__u16 nla_start_poll_type[2] = {NFC_ATTR_DEVICE_INDEX,
+					 NFC_ATTR_PROTOCOLS};
+	void *nla_start_poll_data[2] = {&self->dev_idex, &self->proto};
+	int nla_start_poll_len[2] = {4, 4};
+	pthread_t thread_t;
+	int status;
+	int rc;
+
+	rc = pthread_create(&thread_t, NULL, virtual_poll_start,
+			    (void *)&self->virtual_nci_fd);
+	ASSERT_GT(rc, -1);
+
+	rc = send_cmd_mt_nla(self->sd, self->fid, self->pid,
+			     NFC_CMD_START_POLL, 2, nla_start_poll_type,
+			     nla_start_poll_data, nla_start_poll_len);
+	EXPECT_EQ(rc, 0);
+
+	pthread_join(thread_t, (void **)&status);
+	ASSERT_EQ(status, 0);
+
+	rc = pthread_create(&thread_t, NULL, virtual_poll_stop,
+			    (void *)&self->virtual_nci_fd);
+	ASSERT_GT(rc, -1);
+
+	rc = send_cmd_with_idx(self->sd, self->fid, self->pid,
+			       NFC_CMD_STOP_POLL, self->dev_idex);
+	EXPECT_EQ(rc, 0);
+
+	pthread_join(thread_t, (void **)&status);
+	ASSERT_EQ(status, 0);
+}
+
+TEST_F(NCI, deinit)
+{
+	struct msgtemplate msg;
+	pthread_t thread_t;
+	int status;
+	int rc;
+
+	rc = get_nci_devid(self->sd, self->fid, self->pid, self->dev_idex,
+			   &msg);
+	ASSERT_EQ(rc, 0);
+	EXPECT_EQ(get_dev_enable_state(&msg), 1);
+
+	if (self->isNCI2)
+		rc = pthread_create(&thread_t, NULL, virtual_deinit_v2,
+				    (void *)&self->virtual_nci_fd);
+	else
+		rc = pthread_create(&thread_t, NULL, virtual_deinit,
+				    (void *)&self->virtual_nci_fd);
+	ASSERT_GT(rc, -1);
+
+	rc = send_cmd_with_idx(self->sd, self->fid, self->pid,
+			       NFC_CMD_DEV_DOWN, self->dev_idex);
+	EXPECT_EQ(rc, 0);
+
+	pthread_join(thread_t, (void **)&status);
+	self->open_state = 0;
+	ASSERT_EQ(status, 0);
+
+	rc = get_nci_devid(self->sd, self->fid, self->pid, self->dev_idex,
+			   &msg);
+	ASSERT_EQ(rc, 0);
+	EXPECT_EQ(get_dev_enable_state(&msg), 0);
+}
+
+TEST_HARNESS_MAIN
-- 
2.25.1


^ permalink raw reply related	[relevance 50%]

* Re: [linux-nfc] Re: [PATCH 2/2] nfc: s3fwrn5: i2c: Enable optional clock from device tree
  @ 2021-05-20 11:40 90%             ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-05-20 11:40 UTC (permalink / raw)
  To: Krzysztof Kozlowski
  Cc: Stephan Gerhold, Bongsu Jeon, David S. Miller, Jakub Kicinski,
	Rob Herring, linux-nfc, netdev, devicetree, linux-kernel,
	~postmarketos/upstreaming

On Thu, May 20, 2021 at 12:58 AM Krzysztof Kozlowski
<krzysztof.kozlowski@canonical.com> wrote:
>
> On 19/05/2021 04:07, Stephan Gerhold wrote:
> > On Tue, May 18, 2021 at 11:25:55AM -0400, Krzysztof Kozlowski wrote:
> >> On 18/05/2021 11:00, Stephan Gerhold wrote:
> >>> On Tue, May 18, 2021 at 10:30:43AM -0400, Krzysztof Kozlowski wrote:
> >>>> On 18/05/2021 09:39, Stephan Gerhold wrote:
> >>>>> s3fwrn5 has a NFC_CLK_REQ output GPIO, which is asserted whenever
> >>>>> the clock is needed for the current operation. This GPIO can be either
> >>>>> connected directly to the clock provider, or must be monitored by
> >>>>> this driver.
> >>>>>
> >>>>> As an example for the first case, on many Qualcomm devices the
> >>>>> NFC clock is provided by the main PMIC. The clock can be either
> >>>>> permanently enabled (clocks = <&rpmcc RPM_SMD_BB_CLK2>) or enabled
> >>>>> only when requested through a special input pin on the PMIC
> >>>>> (clocks = <&rpmcc RPM_SMD_BB_CLK2_PIN>).
> >>>>>
> >>>>> On the Samsung Galaxy A3/A5 (2015, Qualcomm MSM8916) this mechanism
> >>>>> is used with S3FWRN5's NFC_CLK_REQ output GPIO to enable the clock
> >>>>> only when necessary. However, to make that work the s3fwrn5 driver
> >>>>> must keep the RPM_SMD_BB_CLK2_PIN clock enabled.
> >>>>
> >>>> This contradicts the code. You wrote that pin should be kept enabled
> >>>> (somehow... by driver? by it's firmware?) but your code requests the
> >>>> clock from provider.
> >>>>
> >>>
> >>> Yeah, I see how that's a bit confusing. Let me try to explain it a bit
> >>> better. So the Samsung Galaxy A5 (2015) has a "S3FWRN5XS1-YF30", some
> >>> variant of S3FWRN5 I guess. That S3FWRN5 has a "XI" and "XO" pin in the
> >>> schematics. "XO" seems to be floating, but "XI" goes to "BB_CLK2"
> >>> on PM8916 (the main PMIC).
> >>>
> >>> Then, there is "GPIO2/NFC_CLK_REQ" on the S3FWRN5. This goes to
> >>> GPIO_2_NFC_CLK_REQ on PM8916. (Note: I'm talking about two different
> >>> GPIO2 here, one on S3FWRN5 and one on PM8916, they just happen to have
> >>> the same number...)
> >>>
> >>> So in other words, S3FWRN5 gets some clock from BB_CLK2 on PM8916,
> >>> and can tell PM8916 that it needs the clock via GPIO2/NFC_CLK_REQ.
> >>>
> >>> Now the confusing part is that the rpmcc/clk-smd-rpm driver has two
> >>> clocks that represent BB_CLK2 (see include/dt-bindings/clock/qcom,rpmcc.h):
> >>>
> >>>   - RPM_SMD_BB_CLK2
> >>>   - RPM_SMD_BB_CLK2_PIN
> >>>
> >>> (There are also *_CLK2_A variants but they are even more confusing
> >>>  and not needed here...)
> >>>
> >>> Those end up in different register settings in PM8916. There is one bit
> >>> to permanently enable BB_CLK2 (= RPM_SMD_BB_CLK2), and one bit to enable
> >>> BB_CLK2 based on the status of GPIO_2_NFC_CLK_REQ on PM8916
> >>> (= RPM_SMD_BB_CLK2_PIN).
> >>>
> >>> So there is indeed some kind of "AND" inside PM8916 (the register bit
> >>> and "NFC_CLK_REQ" input pin). To make that "AND" work I need to make
> >>> some driver (here: the s3fwrn5 driver) enable the clock so the register
> >>> bit in PM8916 gets set.
> >>
> >> Thanks for the explanation, it sounds good. The GPIO2 (or how you call
> >> it NFC_CLK_REQ) on S3FWRN5 looks like non-configurable from Linux point
> >> of view. Probably the device firmware plays with it always or at least
> >> handles it in an unknown way for us.
> >>
> >
> > FWIW, I was looking at some more s3fwrn5 code yesterday and came
> > across this (in s3fwrn5_nci_rf_configure()):
> >
> >       /* Set default clock configuration for external crystal */
> >       fw_cfg.clk_type = 0x01;
> >       fw_cfg.clk_speed = 0xff;
> >       fw_cfg.clk_req = 0xff;
> >       ret = nci_prop_cmd(info->ndev, NCI_PROP_FW_CFG,
> >               sizeof(fw_cfg), (__u8 *)&fw_cfg);
> >       if (ret < 0)
> >               goto out;
> >
> > It does look quite suspiciously like that configures how s3fwrn5 expects
> > the clock and possibly (fw_cfg.clk_req?) how GPIO2 behaves. But it's not
> > particularly useful without some documentation for the magic numbers.
>
> Right, without documentation of FW protocol there is not much we can
> deduct here. There is no proof even that the comment matches actual code.
>
> Dear Bongsu,
> Maybe you could share some details about clock selection?

These configuration values depend on the HW circuit for NFC.

There are  two types of fw_cfg.clk_type for N5.
0x01 : external XTAL ( don't need to control the clock because XTAL
always supplies
the NFC clock automatically.)
0x00 : PLL clock (need to control clock. )

There are three types of fw_cfg.clk_speed for N5.
0xFF : for external XTAL
0x00 : 24M for PLL.
0x01 : 19.12M for PLL.

There are two types of fw_cfg.clk_req for N5.
0xFF: NFC firmware controls CLK Req when NFC needs the external clock.
0xF0: NFC firmware doesn't control CLK Req.

>
> >
> > Personally, I just skip all firmware/RF configuration (which works thanks
> > to commit 4fb7b98c7be3 ("nfc: s3fwrn5: skip the NFC bootloader mode")).
> > That way, S3FWRN5 just continues using the proper configuration
> > that was loaded by the vendor drivers at some point. :)
>
> But isn't that configuration lost after power off?
>

If you skip all firmware/RF configuration, you can use  the preserved
firmware and
RF configuration on the chip.

>
> Best regards,
> Krzysztof

^ permalink raw reply	[relevance 90%]

* Re: [PATCH] selftests: nci: fix grammatical errors
  @ 2021-09-16 11:21 90% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-09-16 11:21 UTC (permalink / raw)
  To: Xiang wangx; +Cc: shuah, Bongsu Jeon, netdev, linux-kselftest, linux-kernel

Actually I asked to fix grammatical errors in the subject.
  For example => selftests: nci: replace unsigned int with int

 And please change the log in more detail and  put a period at the end
of the log.
 For example => Should not use comparison of unsigned expressions < 0.

In addition to that, please send patch version 2 with changelog.
 For example=> [PATCH v2 net] ~~~~.


On Thu, Sep 16, 2021 at 7:53 PM Xiang wangx <wangxiang@cdjrlc.com> wrote:
>
> Should not use unsigned expression compared with zero
>
> Signed-off-by: Xiang wangx <wangxiang@cdjrlc.com>
> ---
>  tools/testing/selftests/nci/nci_dev.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/nci/nci_dev.c b/tools/testing/selftests/nci/nci_dev.c
> index e1bf55dabdf6..162c41e9bcae 100644
> --- a/tools/testing/selftests/nci/nci_dev.c
> +++ b/tools/testing/selftests/nci/nci_dev.c
> @@ -746,7 +746,7 @@ int read_write_nci_cmd(int nfc_sock, int virtual_fd, const __u8 *cmd, __u32 cmd_
>                        const __u8 *rsp, __u32 rsp_len)
>  {
>         char buf[256];
> -       unsigned int len;
> +       int len;
>
>         send(nfc_sock, &cmd[3], cmd_len - 3, 0);
>         len = read(virtual_fd, buf, cmd_len);
> --
> 2.20.1
>

^ permalink raw reply	[relevance 90%]

* Re: [PATCH v2] selftests: nci: replace unsigned int with int
  @ 2021-09-16 12:07 90% ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2021-09-16 12:07 UTC (permalink / raw)
  To: Xiang wangx; +Cc: Bongsu Jeon, shuah, netdev, linux-kselftest, linux-kernel

I asked you two things.
Please check them below.

On Thu, Sep 16, 2021 at 8:54 PM Xiang wangx <wangxiang@cdjrlc.com> wrote:
>
> Should not use comparison of unsigned expressions < 0

Please put '.' at the end of the log and add the changelog.
For example
=> Should not use comparison of unsigned expressions < 0.

>
> Signed-off-by: Xiang wangx <wangxiang@cdjrlc.com>
> ---

Please add the change log here.
For example =>
Changes since v1
* Change commit log

>  tools/testing/selftests/nci/nci_dev.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/nci/nci_dev.c b/tools/testing/selftests/nci/nci_dev.c
> index e1bf55dabdf6..162c41e9bcae 100644
> --- a/tools/testing/selftests/nci/nci_dev.c
> +++ b/tools/testing/selftests/nci/nci_dev.c
> @@ -746,7 +746,7 @@ int read_write_nci_cmd(int nfc_sock, int virtual_fd, const __u8 *cmd, __u32 cmd_
>                        const __u8 *rsp, __u32 rsp_len)
>  {
>         char buf[256];
> -       unsigned int len;
> +       int len;
>
>         send(nfc_sock, &cmd[3], cmd_len - 3, 0);
>         len = read(virtual_fd, buf, cmd_len);
> --
> 2.20.1
>

^ permalink raw reply	[relevance 90%]

* Re: [PATCH] nfc: virtual_ncidev: change default device permissions
       [not found]     ` <CGME20211125141522epcas2p21d45e3406fe76bdb17048553f8681af9@epcms2p2>
@ 2021-11-26  6:11 78%   ` 전봉수
  0 siblings, 0 replies; 79+ results
From: 전봉수 @ 2021-11-26  6:11 UTC (permalink / raw)
  To: Thadeu Lima de Souza Cascardo, netdev; +Cc: linux-kernel, krzysztof.kozlowski

 On 25/11/2021 15:14, Thadeu Lima de Souza Cascardo wrote:
> Device permissions is S_IALLUGO, with many unnecessary bits. Remove them
> and also remove read and write permissions from group and others.
> 
> Before the change:
> crwsrwsrwt    1 0        0          10, 125 Nov 25 13:59 /dev/virtual_nci
> 
> After the change:
> crw-------    1 0        0          10, 125 Nov 25 14:05 /dev/virtual_nci
> 
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
> ---
>  drivers/nfc/virtual_ncidev.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c
> index 221fa3bb8705..f577449e4935 100644
--- a/drivers/nfc/virtual_ncidev.c
> +++ b/drivers/nfc/virtual_ncidev.c
> @@ -202,7 +202,7 @@ static int __init virtual_ncidev_init(void)
> 	 miscdev.minor = MISC_DYNAMIC_MINOR;
> 	 miscdev.name = "virtual_nci";
> 	 miscdev.fops = &virtual_ncidev_fops;
> -	 miscdev.mode = S_IALLUGO;
> +	 miscdev.mode = 0600;
> 
> 	 return misc_register(&miscdev);
> }
> -- 

Reviewed-by: Bongsu Jeon <bongsu.jeon@samsung.com>


Thanks.

^ permalink raw reply	[relevance 78%]

* Re: [PATCH] nfc: virtual_ncidev: Add variable to check if ndev is running
       [not found]       ` <CGME20231119164714epcas2p2c0480d014abc4f0f780c714a445881ca@epcms2p4>
@ 2023-11-20  4:47 99%     ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2023-11-20  4:47 UTC (permalink / raw)
  To: Nguyen Dinh Phi, Bongsu Jeon, krzysztof.kozlowski
  Cc: netdev, linux-kernel, syzbot+6eb09d75211863f15e3e


On 20/11/2023 01:47, Nguyen Dinh Phi wrote:

> syzbot reported an memory leak that happens when an skb is add to
> send_buff after virtual nci closed.
> This patch adds a variable to track if the ndev is running before
> handling new skb in send function.
> 
> Reported-by: syzbot+6eb09d75211863f15e3e@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/lkml/00000000000075472b06007df4fb@google.com
> Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
> ---
>  drivers/nfc/virtual_ncidev.c | 9 +++++++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c
> index b027be0b0b6f..ac8226db54e2 100644
> --- a/drivers/nfc/virtual_ncidev.c
> +++ b/drivers/nfc/virtual_ncidev.c
> @@ -20,26 +20,31 @@
>                                   NFC_PROTO_ISO14443_MASK | \
>                                   NFC_PROTO_ISO14443_B_MASK | \
>                                   NFC_PROTO_ISO15693_MASK)
> +#define NCIDEV_RUNNING 0
This define isn't used.

>  
>  struct virtual_nci_dev {
>          struct nci_dev *ndev;
>          struct mutex mtx;
>          struct sk_buff *send_buff;
>          struct wait_queue_head wq;
> +        bool running;
>  };
>  
>  static int virtual_nci_open(struct nci_dev *ndev)
>  {
> +        struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
> +
> +        vdev->running = true;
>          return 0;
>  }
>  
>  static int virtual_nci_close(struct nci_dev *ndev)
>  {
>          struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
> -
>          mutex_lock(&vdev->mtx);
>          kfree_skb(vdev->send_buff);
>          vdev->send_buff = NULL;
> +        vdev->running = false;
>          mutex_unlock(&vdev->mtx);
>  
>          return 0;
> @@ -50,7 +55,7 @@ static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
>          struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
>  
>          mutex_lock(&vdev->mtx);
> -        if (vdev->send_buff) {
> +        if (vdev->send_buff || !vdev->running) {

Dear Krzysztof,

I agree this defensive code.
But i think NFC submodule has to avoid this situation.(calling send function of closed nci_dev)
Could you check this?

Best regards,
Bongsu

^ permalink raw reply	[relevance 99%]

* Re: [PATCH] nfc: virtual_ncidev: Add variable to check if ndev is running
       [not found]       ` <CGME20231120184433epcas2p23e9f5db776d46ad8dd77a16dd326c1bc@epcms2p1>
@ 2023-11-21  1:31 99%     ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2023-11-21  1:31 UTC (permalink / raw)
  To: Krzysztof Kozlowski, Nguyen Dinh Phi, Bongsu Jeon
  Cc: netdev, linux-kernel, syzbot+6eb09d75211863f15e3e

On 20/11/2023 19:23, Phi Nguyen wrote:

> The issue arises when an skb is added to the send_buff after invoking 
> ndev->ops->close() but before unregistering the device. In such cases, 
> the virtual device will generate a copy of skb, but with no consumer 
> thereafter. Consequently, this object persists indefinitely.
> 
> This problem seems to stem from the existence of time gaps between 
> ops->close() and the destruction of the workqueue. During this interval, 
> incoming requests continue to trigger the send function.

Dear Krzysztof,

Even though i agree on this patch, i think that NFC subsystem could handle this scenario not to trigger the send function after close.
Do you think it would be better that each nci driver has the responsibility to handle this scenario?

Best regards,
Bongsu

^ permalink raw reply	[relevance 99%]

* Re: [PATCH v2] nfc: virtual_ncidev: Add variable to check if ndev is running
       [not found]     ` <CGME20231121075419epcas2p280fa7111de7f37b46f460b6c61ff7175@epcms2p2>
@ 2023-11-21  8:17 99%   ` Bongsu Jeon
  0 siblings, 0 replies; 79+ results
From: Bongsu Jeon @ 2023-11-21  8:17 UTC (permalink / raw)
  To: Nguyen Dinh Phi, Bongsu Jeon, Krzysztof Kozlowski
  Cc: syzbot+6eb09d75211863f15e3e, netdev, linux-kernel

On 21/11/2023 16:54, Nguyen Dinh Phi wrote:
> syzbot reported an memory leak that happens when an skb is add to
> send_buff after virtual nci closed.
> This patch adds a variable to track if the ndev is running before
> handling new skb in send function.
> 
> Signed-off-by: Nguyen Dinh Phi <phind.uet@gmail.com>
> Reported-by: syzbot+6eb09d75211863f15e3e@syzkaller.appspotmail.com
> Closes: https://lore.kernel.org/lkml/00000000000075472b06007df4fb@google.com
> ---
> V2:
>     - Remove unused macro.
>     - Re-adding a line that was removed wrongly.
>  drivers/nfc/virtual_ncidev.c | 7 ++++++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/nfc/virtual_ncidev.c b/drivers/nfc/virtual_ncidev.c
> index b027be0b0b6f..590b038e449e 100644
> --- a/drivers/nfc/virtual_ncidev.c
> +++ b/drivers/nfc/virtual_ncidev.c
> @@ -26,10 +26,14 @@ struct virtual_nci_dev {
>  	struct mutex mtx;
>  	struct sk_buff *send_buff;
>  	struct wait_queue_head wq;
> +	bool running;
>  };
>  
>  static int virtual_nci_open(struct nci_dev *ndev)
>  {
> +	struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
> +
> +	vdev->running = true;
>  	return 0;
>  }
>  
> @@ -40,6 +44,7 @@ static int virtual_nci_close(struct nci_dev *ndev)
>  	mutex_lock(&vdev->mtx);
>  	kfree_skb(vdev->send_buff);
>  	vdev->send_buff = NULL;
> +	vdev->running = false;
>  	mutex_unlock(&vdev->mtx);
>  
>  	return 0;
> @@ -50,7 +55,7 @@ static int virtual_nci_send(struct nci_dev *ndev, struct sk_buff *skb)
>  	struct virtual_nci_dev *vdev = nci_get_drvdata(ndev);
>  
>  	mutex_lock(&vdev->mtx);
> -	if (vdev->send_buff) {
> +	if (vdev->send_buff || !vdev->running) {
>  		mutex_unlock(&vdev->mtx);
>  		kfree_skb(skb);
>  		return -1;
> -- 
> 2.39.2


Reviewed-by: Bongsu Jeon

Best regards,
Bongsu

^ permalink raw reply	[relevance 99%]

Results 1-79 of 79 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
     [not found]     <CGME20201116011205epcms2p566dbc946d6c7a0198d09b3a872e85f33@epcms2p5>
2020-11-16  1:12 95% ` [PATCH net-next 1/3] nfc: s3fwrn5: Remove the max_payload Bongsu Jeon
     [not found]     <CGME20201116011755epcms2p7f7232e0865e8e1bc11a4b528c10d3571@epcms2p7>
2020-11-16  1:17 99% ` [PATCH net-next 2/3] nfc: s3fwrn5: Fix the misspelling in a comment Bongsu Jeon
     [not found]     <CGME20201116011950epcms2p68117cc4a7228db2baecb7d4a4840b955@epcms2p6>
2020-11-16  1:19 99% ` [PATCH net-next 3/3] nfc: s3fwrn5: Change the error code Bongsu Jeon
     [not found]     <CGME20201117011420epcms2p28407a6596fdf1e63cb84af98fa768566@epcms2p2>
2020-11-17  1:14 99% ` [PATCH net-next v2 0/3] nfc: s3fwrn5: Refactor the s3fwrn5 driver Bongsu Jeon
     [not found]     <CGME20201117011611epcms2p22fb0315814144e94856a96014c376a04@epcms2p2>
2020-11-17  1:16 95% ` [PATCH net-next v2 1/3] nfc: s3fwrn5: Remove the max_payload Bongsu Jeon
2020-11-17  7:42       ` krzk
2020-11-17  8:14 78%     ` Bongsu Jeon
2020-11-17  8:38           ` Krzysztof Kozlowski
2020-11-17 12:52 78%         ` Bongsu Jeon
     [not found]     <CGME20201117011742epcms2p1fb85ba231b3a1673d97af4bc1479744f@epcms2p1>
2020-11-17  1:17 99% ` [PATCH net-next v2 2/3] nfc: s3fwrn5: Fix the misspelling in a comment Bongsu Jeon
     [not found]     <CGME20201117011850epcms2p568af074144630cd0f02b3a7f7eff8d1a@epcms2p5>
2020-11-17  1:18 99% ` [PATCH net-next v2 3/3] nfc: s3fwrn5: Change the error code Bongsu Jeon
     [not found]     <CGME20201117053759epcms2p80e47c3e9be01d564c775c045a42678f7@epcms2p8>
2020-11-17  5:37 75% ` [PATCH net-next] net/nfc/nci: Support NCI 2.x initial sequence Bongsu Jeon
2020-11-18  1:57       ` Jakub Kicinski
2020-11-18  4:29 78%     ` Bongsu Jeon
     [not found]     <CGME20201117080824epcms2p36f70e06e2d8bd51d1af278b26ca65725@epcms2p3>
2020-11-17  8:08 95% ` [PATCH net-next v2 1/3] nfc: s3fwrn5: Remove the max_payload Bongsu Jeon
     [not found]     <CGME20201117080950epcms2p4d332688ce351321c3222734bca680b57@epcms2p4>
2020-11-17  8:09 99% ` [PATCH net-next v2 2/3] nfc: s3fwrn5: Fix the misspelling in a comment Bongsu Jeon
     [not found]     <CGME20201117081137epcms2p84b5dd8d84ca608f44b0bb722b48f50b1@epcms2p8>
2020-11-17  8:11 98% ` [PATCH net-next v2 3/3] nfc: s3fwrn5: Change the error code Bongsu Jeon
     [not found]     <CGME20201123075526epcms2p59410a8ba942f8942f53a593d9df764d0@epcms2p5>
2020-11-23  7:55 99% ` [PATCH net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Support a UART interface Bongsu Jeon
2020-11-23  8:01       ` krzk
2020-11-24 11:39 90%     ` Bongsu Jeon
2020-11-24 11:41           ` krzk
2020-11-25  3:08 90%         ` Bongsu Jeon
     [not found]     <CGME20201123075658epcms2p5a6237314f7a72a2556545d3f96261c93@epcms2p5>
2020-11-23  7:56 78% ` [PATCH net-next 2/2] " Bongsu Jeon
2020-11-23  8:19       ` krzk
2020-11-24 12:05 89%     ` Bongsu Jeon
2020-11-24 14:15           ` krzk
2020-11-25  4:01 90%         ` Bongsu Jeon
2020-11-25  4:43 90%           ` Bongsu Jeon
     [not found]     <CGME20201123101208epcms2p71d4c8d66f08fb7a2e10ae422abde3389@epcms2p7>
2020-11-23 10:12 74% ` [PATCH net-next v2] net/nfc/nci: Support NCI 2.x initial sequence Bongsu Jeon
2020-11-26 15:33     [PATCH net-next 1/3] nfc: s3fwrn5: use signed integer for parsing GPIO numbers bongsu.jeon2
2020-11-26 15:33     ` [PATCH net-next 3/3] nfc: s3fwrn5: extract the common phy blocks bongsu.jeon2
2020-11-26 17:12       ` Krzysztof Kozlowski
2020-11-26 23:09 90%     ` Bongsu Jeon
2020-11-26 17:01     ` [PATCH net-next 1/3] nfc: s3fwrn5: use signed integer for parsing GPIO numbers Krzysztof Kozlowski
2020-11-26 22:53 78%   ` Bongsu Jeon
2020-11-27  5:41 90%     ` Bongsu Jeon
2020-11-27 11:22     [PATCH v2 net-next 3/3] nfc: s3fwrn5: extract the common phy blocks bongsu.jeon2
2020-11-28 12:49     ` Krzysztof Kozlowski
2020-11-29  9:55 89%   ` Bongsu Jeon
2020-11-27 13:36     [PATCH net-next v3] net/nfc/nci: Support NCI 2.x initial sequence bongsu.jeon2
2020-12-01  2:48     ` Jakub Kicinski
2020-12-02 22:18 90%   ` Bongsu Jeon
2020-11-30 12:00 90% [PATCH v2 net-next 1/4] dt-bindings: net: nfc: s3fwrn5: Support a UART interface Bongsu jeon
2020-11-30 12:02 90% [PATCH net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
2020-11-30 12:03 61% [PATCH v3 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
2020-11-30 12:05 68% [PATCH v2 net-next 4/4] net: nfc: s3fwrn5: Support a UART interface Bongsu Jeon
2020-12-01 13:50 86% [PATCH v4 net-next 0/4] " Bongsu Jeon
2020-12-01 13:50 90% ` [PATCH v4 net-next 1/4] dt-bindings: net: " Bongsu Jeon
2020-12-01 13:50 90% ` [PATCH v4 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
2020-12-01 13:50 62% ` [PATCH v4 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
2020-12-01 13:50 68% ` [PATCH v4 net-next 4/4] nfc: s3fwrn5: Support a UART interface Bongsu Jeon
2020-12-02 11:47 85% [PATCH v5 net-next 0/4] " Bongsu Jeon
2020-12-02 11:47 90% ` [PATCH v5 net-next 1/4] dt-bindings: net: " Bongsu Jeon
2020-12-02 17:16       ` Krzysztof Kozlowski
2020-12-02 22:16 90%     ` Bongsu Jeon
2020-12-02 11:47 90% ` [PATCH v5 net-next 2/4] nfc: s3fwrn5: reduce the EN_WAIT_TIME Bongsu Jeon
2020-12-02 11:47 62% ` [PATCH v5 net-next 3/4] nfc: s3fwrn5: extract the common phy blocks Bongsu Jeon
2020-12-02 11:47 68% ` [PATCH v5 net-next 4/4] nfc: s3fwrn5: Support a UART interface Bongsu Jeon
2020-12-02 22:31 64% [PATCH net-next v4] net/nfc/nci: Support NCI 2.x initial sequence Bongsu Jeon
2020-12-03 15:39 82% [PATCH net-next] nfc: s3fwrn5: skip the NFC bootloader mode Bongsu Jeon
2020-12-03 22:52 84% [PATCH v2 " Bongsu Jeon
2020-12-07 11:38 90% [PATCH net-next] nfc: s3fwrn5: Change irqflags Bongsu Jeon
2020-12-07 11:51     ` Krzysztof Kozlowski
2020-12-07 13:39 89%   ` Bongsu Jeon
2020-12-07 14:13         ` Krzysztof Kozlowski
2020-12-07 14:26 90%       ` Bongsu Jeon
2020-12-08 14:10 90% [PATCH v2 net-next 0/2] nfc: s3fwrn5: Change I2C interrupt trigger to EDGE_RISING Bongsu Jeon
2020-12-08 14:10 87% ` [PATCH v2 net-next 1/2] dt-bindings: net: nfc: s3fwrn5: Change I2C interrupt trigger type Bongsu Jeon
2020-12-08 14:10 90% ` [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove hard coded interrupt trigger type from the i2c module Bongsu Jeon
2020-12-13  9:58 90% [PATCH net-next] nfc: s3fwrn5: Release the nfc firmware Bongsu Jeon
2020-12-13 10:12 90% [PATCH net-next] nfc: s3fwrn5: Remove the delay for nfc sleep Bongsu Jeon
2020-12-14 11:46 88% [PATCH net-next] nfc: s3fwrn5: Remove unused nci prop commands Bongsu Jeon
2020-12-14 16:02     ` Krzysztof Kozlowski
2020-12-15  3:03 90%   ` Bongsu Jeon
2020-12-14 12:28 90% [PATCH net-next] MAINTAINERS: Update maintainer for SAMSUNG S3FWRN5 NFC Bongsu Jeon
2020-12-14 15:44     ` [linux-nfc] " Krzysztof Kozlowski
2020-12-15  3:01 90%   ` Bongsu Jeon
2020-12-15  6:53 90% [PATCH v2 net-next 0/2] nfc: s3fwrn5: Refactor the s3fwrn5 module Bongsu Jeon
2020-12-15  6:54 90% ` [PATCH v2 net-next 1/2] nfc: s3fwrn5: Remove the delay for NFC sleep Bongsu Jeon
2020-12-15  6:54 88% ` [PATCH v2 net-next 2/2] nfc: s3fwrn5: Remove unused NCI prop commands Bongsu Jeon
2020-12-28  1:46 90% [PATCH net-next] net: nfc: nci: Change the NCI close sequence Bongsu Jeon
2020-12-28  9:45 71% [PATCH net-next] nfc: Add a virtual nci device driver Bongsu Jeon
2020-12-28 21:16     ` Jakub Kicinski
2020-12-31  5:22 90%   ` Bongsu Jeon
2021-01-04 19:48         ` Jakub Kicinski
2021-01-05 23:16 90%       ` Bongsu Jeon
2021-01-06 17:01             ` Jakub Kicinski
2021-01-07 22:38 90%           ` Bongsu Jeon
2020-12-31  2:59 89% [PATCH net-next v2] net: nfc: nci: Change the NCI close sequence Bongsu Jeon
2021-01-18 20:55 90% [PATCH net] net: nfc: nci: fix the wrong NCI_CORE_INIT parameters Bongsu Jeon
2021-01-18 21:01     ` Jakub Kicinski
2021-01-18 21:19 90%   ` Bongsu Jeon
2021-01-20  1:00     ` patchwork-bot+netdevbpf
2021-01-20  9:54 90%   ` Bongsu Jeon
2021-01-27 13:08 89% [PATCH net-next v4 0/2] Add nci suit and virtual nci device driver Bongsu Jeon
2021-01-27 13:08 73% ` [PATCH net-next v4 1/2] nfc: Add a " Bongsu Jeon
2021-01-27 13:08 50% ` [PATCH net-next v4 2/2] selftests: Add nci suite Bongsu Jeon
2021-05-18 13:39     [PATCH 1/2] dt-bindings: net: nfc: s3fwrn5: Add optional clock Stephan Gerhold
2021-05-18 13:39     ` [PATCH 2/2] nfc: s3fwrn5: i2c: Enable optional clock from device tree Stephan Gerhold
2021-05-18 14:30       ` [linux-nfc] " Krzysztof Kozlowski
2021-05-18 15:00         ` Stephan Gerhold
2021-05-18 15:25           ` [linux-nfc] " Krzysztof Kozlowski
2021-05-19  8:07             ` Stephan Gerhold
2021-05-19 15:58               ` Krzysztof Kozlowski
2021-05-20 11:40 90%             ` Bongsu Jeon
2021-09-16 10:51     [PATCH] selftests: nci: fix grammatical errors Xiang wangx
2021-09-16 11:21 90% ` Bongsu Jeon
2021-09-16 11:52     [PATCH v2] selftests: nci: replace unsigned int with int Xiang wangx
2021-09-16 12:07 90% ` Bongsu Jeon
2021-11-25 14:14     [PATCH] nfc: virtual_ncidev: change default device permissions Thadeu Lima de Souza Cascardo
     [not found]     ` <CGME20211125141522epcas2p21d45e3406fe76bdb17048553f8681af9@epcms2p2>
2021-11-26  6:11 78%   ` 전봉수
2023-11-20 18:44     [PATCH] nfc: virtual_ncidev: Add variable to check if ndev is running Krzysztof Kozlowski
2023-11-19 16:47     ` Nguyen Dinh Phi
     [not found]       ` <CGME20231119164714epcas2p2c0480d014abc4f0f780c714a445881ca@epcms2p4>
2023-11-20  4:47 99%     ` Bongsu Jeon
     [not found]       ` <CGME20231120184433epcas2p23e9f5db776d46ad8dd77a16dd326c1bc@epcms2p1>
2023-11-21  1:31 99%     ` Bongsu Jeon
2023-11-21  7:53     [PATCH v2] " Nguyen Dinh Phi
     [not found]     ` <CGME20231121075419epcas2p280fa7111de7f37b46f460b6c61ff7175@epcms2p2>
2023-11-21  8:17 99%   ` Bongsu Jeon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).